-
chapter-1 데이터에서 인사이트 발견하기이것이 데이터 분석이다 with 파이썬 2021. 9. 26. 17:19
1.1 탐색적 데이터 분석의 과정¶
탐색적 데이터 분석은 데이터의 정보를 파악하며 문제 해결에 필요한 힌트를 분석하는 과정입니다. 이제, 탐색적 데이터 분석의 과정을 몇 가지 예제와 함께 알아보겠습니다.
데이터와의 첫 만남¶
우리가 실제로 접하는 대부분의 데이터는 아직 분석에 활용된 적이 없는 혹은 정제되지 않은 데이터입니다. 이러한 데이터를 raw data라고 부릅니다(이후 '데이터'로 통칭합니다). 탐색적 데이터 분석은 데이터를 열어보는 상황에서부터 시작되며 이때부터 다음과 같은 과정을 수행합니다.
1. 데이터의 출처와 주제에 대해 이해합니다.¶
우선 데이터가 어디에서 생성된 것이고, 어떻게 수집된 것인지를 이해하는 것이 먼저입니다. 데이터의 이름, 구성요서, 그리고 데이터의 출처와 주제 등에 대해 가장 먼저 조사합니다.
2. 데이터의 크기를 알아봅니다.¶
데이터의 대략적인 양이나 개수를 알아보는 단계입니다. 데이터의 크기에 따라서 특별한 종류의 샘플링이 필요하기도 하고, 어떤 방식으로 데이터를 처리할지도 달라질 수 있기 때문입니다.
3. 데이터의 구성 요소(피처)를 살펴봅니다.¶
마지막으로 데이터의 피처를 살펴봅니다. 피처란 데이터를 구성하는 요소를 의미합니다. 만약[그림1-1]과 같이 어떤 학급의 신체검사 결과를 기록한 데이터가 있다고 할 때, 키와 몸무게 그리고 시력 같은 측정요소를 피처라고 부릅니다. 데이터를 탐색하는 단계에서 피처를 살펴보는 것은 아주 중요한 과정입니다.
샘플링(Sampling)¶
- 샘플링이란 어떤 자료로부터 일부의 값을 추출하는 행위를 의미합니다. 분석하고자 하는 데이터가 너무 크거나 전체 데이터를 사용할 수 없는 경우에는 샘플링된 데이터를 분석하는 것이 좋은 대안이 될 수 있습니다.
데이터의 속성 탐색하기¶
데이터를 탐색하는 단계에서 데이터의 외형적인 힌트를 얻었다면 이번 단계에서는 데이터의 실제적인 내용을 탐색합니다. 실제적인 내용 탐색의 과정에서는 크게 피처의 속성 탐색, 그리고 피처 간의 상관 관계 탐색 이렇게 두 가지를 시행합니다.
피처의 속성 탐색¶
앞서 살펴본 학급의 신체겁사 데이터에서는 어떤 속성을 탐색할 수 있을까요? 우선 가장 쉽게 떠올릴 수 있는 것은 학급의 평균 키를 계산하는 것입니다. 평균을 구하는 것뿐만 아니라, 학창 시철 배웠던 표준편차, 중앙값, 데이터의 사분위 수 등의 통계값을 구할 수도 있습니다. 이는 [그림 1-2]와 같이 피처의 측정 가능한 정량적 속성을 정의하는 것이라고 할 수 있습니다.
피처의 속성 탐색 과정에서 가장 중요한 것은 데이터에 질문을 던지는 것입니다. 피처의 속성 탐색은 '우리 반의 평균 키는 몇이나 될까?'와 같은 질문에서부터 출발하기 때문입니다. 이러한 질문을 던지는 것이 좋은 데이터 분석가가 되는 첫걸음이라고 할 수 있습니다.
피처 간의 상관 관계 탐색¶
피처 간의 상관 관계 탐색이란 여러 개의 피처가 서로에게 미치는 영향력을 알아보는 것입니다. 만약 학급의 신체검사 데이터를 살펴본 뒤, '우리 학급은 비만이 아닐까?'라는 질문을 했다고 가정해봅시다. 그렇다면 우리는 '몸무게'라는 피처를 살펴볼 것입니다. 그리고 이를 통해 가정을 확인할 것입니다. 하지만 우리가 한 가지 더 고려해야 할 점은 몸무게는 키와도 관계가 있다는 것입니다. 이런 상황에서 필요한 것이 피처 간의 상관 관계탐색입니다. 데이터 분석에서는 이를 통계적인 방법으로 알아볼수 있으며, 이는 피처 간의 공분산, 혹은 상관 계수와 같은 개념을 포함합니다. 이 개념들에 대해서는 이후 예제에서 조금 더 자세히 알아보겠습니다.
탐색한 데이터의 시각화¶
마지막 단계는 탐색한 데이터의 시각화 단게입니다. 지금까지의 과정을 통해 어느 정도 데이터를 파악했다면 이를 효과적으로 시각화할 차례입니다. 데이터 시각화 수치적 자료만 가지고는 파악하기 힘든 패턴이나 인사이트를 발견하는 데 유용하기 때문입니다. 키와 몸무게의 상관 관계는 쉽게 발견하기 어렵지만 이를 그래프로 시각화하면 직관적으로 파악할 수 있습니다.
1.2 멕시코풍 프랜차이즈 chipotle의 주문 데이터 분석하기¶
첫 번째 예제의 목표는 토이 데이터(분석에 용이한 형태로 만들어진 연습용 데이터 세트)를 활용한 데이터 분석에 익숙해지는 것입니다. 우리가 분석해볼 첫 번째 토이 데이터는 멕시코풍 프랜차이즈'chipotle'라는 음식점의 주문 데이터입니다.
chipotle 데이터셋의 기초 정보 출력하기¶
In [1]:import pandas as pd file_path='data/chipotle.tsv' chipo=pd.read_csv(file_path,sep='\t') print(chipo.shape) print("-----------------") print(chipo.info())
(4622, 5) ----------------- <class 'pandas.core.frame.DataFrame'> RangeIndex: 4622 entries, 0 to 4621 Data columns (total 5 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 order_id 4622 non-null int64 1 quantity 4622 non-null int64 2 item_name 4622 non-null object 3 choice_description 3376 non-null object 4 item_price 4622 non-null object dtypes: int64(2), object(3) memory usage: 180.7+ KB None
그리고 shape()와 info() 함수를 호출하면 위와 같은 실행 결과를 볼 수 있습니다. shape()는 데이터의 행과 열의 크기를 반환하고, info()는 행의 구성 정보와 열의 구성 정보를 나타냅니다. 실행 결과를 보면 데이터가 4,622개의 행과 5개의 피처로 구성되어 있음을 알 수 있습니다. 또한 order_id와 quantity는 int64(숫자), 나머지 3개의 피처는 object라는 타입으로 이루어져 있다는 것도 알수있습니다. 그런데 한 가지 특이한 정보는 choice_description 피처가 3,376개의 non-null object로 구성되어 있다는 것입니다. 이정보는 무엇을 의미할까요?
데이터 프레임에서 object 타입은 일반적으로 문자열을 의미합니다. 그리고 null이라는 용어는 데이터가 비어 있는 것을 의미합니다. 이를 결측값이라고 합니다. 즉 '3376 non-null object'라는 것은 3,376개의 비어 있지 않은 문자열 데이터가 있다는 정보입니다. 하지만 데이터의 개수는 4,622개이므로 choice_description 피처는 1,245개의 결측값이 존재합니다.다음 코드를 살펴봅시다. head(10) 함수는 첫 10개의 데이터를 테이블 형태로 출력합니다. 또한 columns(행의 목록)와 index(열의 목록)를 호출하면 데이터의 행과 열에 대한 정보를 함께 출력할 수 있습니다.
chipotle 데이터셋의 행과 열, 데이터 확인하기¶
In [2]:# chipo라는 데이터 프레임에서 순서대로 10개의 데이터를 보여줍니다. chipo.head(10)
Out[2]:order_id quantity item_name choice_description item_price 0 1 1 Chips and Fresh Tomato Salsa NaN $2.39 1 1 1 Izze [Clementine] $3.39 2 1 1 Nantucket Nectar [Apple] $3.39 3 1 1 Chips and Tomatillo-Green Chili Salsa NaN $2.39 4 2 2 Chicken Bowl [Tomatillo-Red Chili Salsa (Hot), [Black Beans... $16.98 5 3 1 Chicken Bowl [Fresh Tomato Salsa (Mild), [Rice, Cheese, Sou... $10.98 6 3 1 Side of Chips NaN $1.69 7 4 1 Steak Burrito [Tomatillo Red Chili Salsa, [Fajita Vegetables... $11.75 8 4 1 Steak Soft Tacos [Tomatillo Green Chili Salsa, [Pinto Beans, Ch... $9.25 9 5 1 Steak Burrito [Fresh Tomato Salsa, [Rice, Black Beans, Pinto... $9.25 In [3]:print(chipo.columns) print("-----------------") print(chipo.index)
Index(['order_id', 'quantity', 'item_name', 'choice_description', 'item_price'], dtype='object') ----------------- RangeIndex(start=0, stop=4622, step=1)
이때, chipotle 데이터셋 피처의 의미는 각각 다음과 같습니다.
- order_id : 주문 번호
- quantity : 아이템의 주문 수량
- item_name : 주문한 아이템의 이름
- choice_description : 주문한 아이템의 상세 선택 옵션
- item_price : 주문 아이템의 가격 정보
이제 본격적으로 이 피처들의 속성을 파악해봅시다.
quantity 와 item_price의 수치적 특징¶
우선 quantity와 item_price의 수치적 특징을 살펴보겠습니다. 이 두 피처는 연속형 피처입니다. 연속형 피처는 키와 몸무게처럼 어떠한 값도 가질 수 있는 연속적인 숫자 형태를 의미합니다.
다음 코드의 출력 결과는 describe() 함수가 나타낸 피처의 기초 통계량입니다. 하지만 현재 유일하게 존재하는 수치형 피처는 quantity뿐이기 때문에, 오직 quantity에 대한 정보만을 출력할 수 있습니다.
describe() 함수로 기초 통계량 출력하기¶
In [4]:# order_id는 숫자의 의미를 가지지 않기 때문에 str으로 변홥합니다. chipo['order_id']=chipo['order_id'].astype(str) print(chipo.describe()) # chipo 데이터 프레임에서 수치형 피처들의 기초 통계량을 확인합니다.
quantity count 4622.000000 mean 1.075725 std 0.410186 min 1.000000 25% 1.000000 50% 1.000000 75% 1.000000 max 15.000000
출력 내용을 분석해보면 아이템의 평균 주문 수량(mean)은 약 1.07이라는 것을 알 수 있습니다. 이는 대부분이 한 아이템에 대해서 1개 정도만 주문했다는 것이고, '한 사람이 같은 메뉴를 여러 개 구매하는 경우는 많지 않다'는 인사이트를 얻을 수 있습니다.
그렇다면 item_price의 수치적 특징은 어떻게 알아볼 수 있을까요? 현재 item_price 피처는 object타입이기 때문에 describe() 함수로 기초 통계량을 확인할 수 없습니다. 이를 위해서는 추가적인 데이터 전처리 작업이 필요한데, 이는 'step3' 데이터 전처리'에서 알아봅시다.order_id와 item_name의 개수¶
다음으로 order_id와 item_name의 개수를 탐색합니다. 이 두 피처는 범주형 피처이기 때문에 unique() 함수를 사용합니다. 이를 통해 피처 내에 몇 개의 범주가 있는지를 확인할 수 있습니다.
unique() 함수로 범주형 피처의 개수 출력하기¶
In [5]:print(len(chipo['order_id'].unique())) # order_id의 개수를 출력합니다. print(len(chipo['item_name'].unique())) # item_name의 개수를 출력합니다.
1834 50
step 2 인사이트 발견:탐색과 시각화하기¶
이제 한 걸음 더 나아가 인사이트를 더 많이 발견할 수 있는 질문을 탐색하며 이를 시각화하는 과정까지 살펴봅시다.
가장많이 주문한 아이템 Top 10¶
먼저, 가장많이 주문한 아이템 Top 10을 분석하기 위해 다음과 같이 DataFrame['column']의 형태에 value_counts() 함수를 적용하는 방식을 사용합니다. DataFrame['column']은 시리즈라는 객체를 반환하는데, value_counts()함수는 오로지 이러한 시리즈 객체에만 적용되기 때문입니다.
가장 많이 주문한 아이템 Top10 출력하기¶
In [6]:# 가장 많이 주문한 아이템 Top 10을 출력합니다. item_count=chipo['item_name'].value_counts()[:10] for idx, (val, cnt) in enumerate(item_count.iteritems(),1): print("Top",idx,":",val,cnt)
Top 1 : Chicken Bowl 726 Top 2 : Chicken Burrito 553 Top 3 : Chips and Guacamole 479 Top 4 : Steak Burrito 368 Top 5 : Canned Soft Drink 301 Top 6 : Chips 211 Top 7 : Steak Bowl 211 Top 8 : Bottled Water 162 Top 9 : Chicken Soft Tacos 115 Top 10 : Chicken Salad Bowl 110
아이템별 주문 개수와 총량¶
이번에는 groupby() 함수를 이용하여 아이템별 주문 개수와 총량을 구해보겠습니다. 판다스의 groupby() 함수는 데이터 프레임에서 특정 피처를 기준으로 그룹을 생성하며 이를 통해 그룹별 연산을 적용할 수 있습니다. 예를 들어 '학급'이라는 그룹을 만들었을 때, '학급별 평균 키','학급별 평균 몸무게' 등을 구하는 것처럼 말이지요.
아이템별 주문 개수와 총량 구하기¶
In [7]:# 아이템별 주문 개수를 출력합니다. order_count=chipo.groupby('item_name')['order_id'].count() order_count[:10] # 아이템별 주문 개수를 출력합니다.
Out[7]:item_name 6 Pack Soft Drink 54 Barbacoa Bowl 66 Barbacoa Burrito 91 Barbacoa Crispy Tacos 11 Barbacoa Salad Bowl 10 Barbacoa Soft Tacos 25 Bottled Water 162 Bowl 2 Burrito 6 Canned Soda 104 Name: order_id, dtype: int64
In [8]:# 아이템별 주문 총량을 계산합니다. item_quantity=chipo.groupby('item_name')['quantity'].sum() item_quantity[:10] # 아이템별 주문 총량을 출력합니다.
Out[8]:item_name 6 Pack Soft Drink 55 Barbacoa Bowl 66 Barbacoa Burrito 91 Barbacoa Crispy Tacos 12 Barbacoa Salad Bowl 10 Barbacoa Soft Tacos 25 Bottled Water 211 Bowl 4 Burrito 6 Canned Soda 126 Name: quantity, dtype: int64
위의 코드 chipo.groupby('item_name')['quantity'].count()는 chipo Dataf에서 item_name을 그룹으로 quantity 피처의 count()를 계산한 것입니다. 이는 아이템별 주문 개수를 의미합니다. 마찬가지 방법으로 chipo.groupby('item_name')['quantity'].sum()은 아이템별 주문 총량을 나타냅니다.
시각화¶
아이템별 주문의 총량을 막대 그래프로 시각화해볼 수도 있습니다. 코드에서는 tolist()와 넘파이의 arrange() 함수를 이용해 x_pos를 선언하고, 0부터 50까지의 숫자를 그래프의 x축 이름으로 사용합니다. 그이유는 50개 아이템의 이름을 x축에 표현하기에는 그래프의 공간이 너무 협소하기 때문입니다. y값(drder_cnt)에는 주문 총량에 해당하는 값인 item_quantity.values.tolist()를 넣어줍니다.
시각화로 분석 결과 살펴보기¶
In [9]:%matplotlib inline import numpy as np import matplotlib.pyplot as plt item_name_list=item_quantity.index.tolist() x_pos=np.arange(len(item_name_list)) order_cnt=item_quantity.values.tolist() plt.bar(x_pos, order_cnt, align='center') plt.ylabel('ordered_item_count') plt.title('Distribution of all orderd item') plt.show()
미니퀴즈 1-1¶
판다스에서 유용하게 사용하는 함수 value_counts()와 unique()의 차이점은 무엇일까요?
각 함수는 어떤 데이터 타입에 적용이 되는지, 어떤 기능을 가지고 있는지, 정확히 어떤 결과값을 반환하는지 실행해봅시다.step 3 데이터 전처리: 전처리 함수 사용하기¶
앞선 내용의 item_price의 수치적 특징을 탐색하는 과정에서 우리는 item_price 피처의 요약 통계를 구할 수 없었습니다. 이는 item_price 피처가 문자열 타입이었기 때문입니다. 이번 단계에서는 이러한 데이터를 전처리하는 방법에 대해 알아보겠습니다.
item_price 피처 살펴보기¶
In [10]:print(chipo.info()) print('-------------') chipo['item_price'].head()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 4622 entries, 0 to 4621 Data columns (total 5 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 order_id 4622 non-null object 1 quantity 4622 non-null int64 2 item_name 4622 non-null object 3 choice_description 3376 non-null object 4 item_price 4622 non-null object dtypes: int64(1), object(4) memory usage: 180.7+ KB None -------------
Out[10]:0 $2.39 1 $3.39 2 $3.39 3 $2.39 4 $16.98 Name: item_price, dtype: object
데이터 전처리에 앞서 item_price 피처를 살펴본 결과, 가격을 나타내는 숫자 앞에 기호가 붙어있는 것을 발견할 수 있습니다. 따라서 이 피처를 수치 데이터로 사용하기 위해서는 '$' 기호를 제거해주는 전처리 작업이 필요합니다.
'$'기호를 제거하는 전처리 방법은 chipo['item_price']에 apply() 함수를 적용함으로써 가능합니다. 그리고 apply() 함수에는 lambda라는 함수 명령어를 추가해줍니다.
apply()와 lambda를 이용해 데이터 전처리하기¶
In [11]:# column 단위 데이터에 apply() 함수로 전처리를 적용합니다. chipo['item_price']=chipo['item_price'].apply(lambda x: float(x[1:])) chipo.describe()
Out[11]:quantity item_price count 4622.000000 4622.000000 mean 1.075725 7.464336 std 0.410186 4.245557 min 1.000000 1.090000 25% 1.000000 3.390000 50% 1.000000 8.750000 75% 1.000000 9.250000 max 15.000000 44.250000 apply() 함수는 시리즈 단위의 연산을 처리하는 기능을 수행하며, sum()이나 mean()과 같이 연산이 정의된 함수를 파라미터로 받습니다. 따라서 피처 단위의 함계나 평균을 구할 수도 있고, 우리가 정의할 새로운 함수 문자열 데이터에서 첫 번째 문자열을 제거한 뒤 나머지 문자열을 수치형으로 바꿔주는 함수를 파라미터로 입력할 수도 있습니다. 위의 코드 lambda x: float(x[1:])는 이를 수행하는 함수를 lambda로 정의하여 입력한 것입니다.
step 4 탐색전 분석: 스무고개로 개념적 탐색 분석하기¶
이번 단계에서는 조금 더 깊이있는 질문을 통해 데이터를 탐색합니다. 이 과정은 마치 데이터와'스무고개'놀이를 하는 과정에 비유할 수 있습니다. 이단계를 거치면 여러분은 파이썬을 활용한 탐색적 데이터 분석에 익숙해질 것입니다. 다음에서 살펴볼 내용 외에도 탐색해보고 싶은 내용을 스스로 정의하여 문제를 해결해보길 바랍니다.
주문당 평균 계산금액 출력하기¶
다음 코드는 order_id로 그룹을 생성한 뒤, item_price 피처에 sum() 함수를 적용하고 mean()함수를 추가한 것입니다. 이를 통행 주문당 평균 계산금액을 구할 수 있습니다. 실행 결과, 한사람이'약18달러가량의 주문을 할 것'이라는 인사이트를 얻을수 있습니다.
주문당 평균 계산금액 출력하기¶
In [12]:# 주문당 평균 계산금액을 출력합니다. chipo.groupby('order_id')['item_price'].sum().mean()
Out[12]:18.811428571428717
한 주문에 10달러 이상 지불한 주문 번호(id) 출력하기¶
다음은로 한 주문에 10달러 이상을 지불한 주문을 찾아봅시다. 우선 order_id 피처(하나의 주문)를 기준으로 그룹을 만들어 quantity, item_price 피러의 합계를 계산합니다. 그리고 이 결과에서 10이상인 값을 필터링합니다. 이에 대한 최종 결과인 results의 index.values를 출력하면 한 주문에 10달러 이상 지불한 id를 출력할 수 있습니다.
한 주문에 10달러 이상 지불한 주문 번호(id) 출력하기¶
In [13]:# 한 주문에 10달러 이상 지불한 id를 출력합니다. chipo_orderid_group=chipo.groupby('order_id').sum() results=chipo_orderid_group[chipo_orderid_group.item_price>=10] print(results[:10]) print(results.index.values)
quantity item_price order_id 1 4 11.56 10 2 13.20 100 2 10.08 1000 2 20.50 1001 2 10.08 1002 2 10.68 1003 2 13.00 1004 2 21.96 1005 3 12.15 1006 8 71.40 ['1' '10' '100' ... '997' '998' '999']
각 아이템의 가격 구하기¶
이번에는 각 아이템의 가격을 계산합니다. chipotle 데이터셋에서는 주어진 데이터만으로 각 아이템의 가격을 대략적으로 유추해야 합니다. 유추 과정은 다음과 같습니다.
-
- chipo[chipo.quantity==1]으로 동일 아이템을 1개만 구매한 주문을 선별합니다.
-
- item_name을 기준으로 groupby 연산을 수행한 뒤, min() 함수로 각 그룹별 최저가를 계산합니다.
-
- item_price를 기준으로 정렬하는 sort_values() 함수를 적용합니다. sort_values()는 series 데이터를 정렬해주는 함수입니다.
각 아이템의 가격 구하기¶
In [14]:# 각 아이템의 가격을 계산합니다. chipo_one_item=chipo[chipo.quantity==1] price_per_item=chipo_one_item.groupby('item_name').min() price_per_item.sort_values(by="item_price", ascending=False)[:10]
Out[14]:order_id quantity choice_description item_price item_name Steak Salad Bowl 1032 1 [Fresh Tomato Salsa, Lettuce] 9.39 Barbacoa Salad Bowl 1283 1 [Fresh Tomato Salsa, Guacamole] 9.39 Carnitas Salad Bowl 1035 1 [Fresh Tomato Salsa, [Rice, Black Beans, Chees... 9.39 Carnitas Soft Tacos 1011 1 [Fresh Tomato Salsa (Mild), [Black Beans, Rice... 8.99 Carnitas Crispy Tacos 1774 1 [Fresh Tomato Salsa, [Fajita Vegetables, Rice,... 8.99 Steak Soft Tacos 1054 1 [Fresh Tomato Salsa (Mild), [Cheese, Sour Cream]] 8.99 Carnitas Salad 1500 1 [[Fresh Tomato Salsa (Mild), Roasted Chili Cor... 8.99 Carnitas Bowl 1007 1 [Fresh Tomato (Mild), [Guacamole, Lettuce, Ric... 8.99 Barbacoa Soft Tacos 1103 1 [Fresh Tomato Salsa, [Black Beans, Cheese, Let... 8.99 Barbacoa Crispy Tacos 110 1 [Fresh Tomato Salsa, Guacamole] 8.99 그리고 각 아이템의 대략적인 가격을 아래와 같이 2개의 그래프로 시각화하여 나타낼 수 있습니다. 각각의 그래프는 아이템의 가격 분포(위쪽 결과)와 가격 히스토그램(아래쪽 결과)을 나타냅니다. 이를 통해 2~4달러, 혹은 6~8달러 정도에 아이템의 가격대가 형성되어 있음을 알 수 있습니다.
In [15]:# 아이템 가격 분포 그래프를 출력합니다. item_name_list=price_per_item.index.tolist() x_pos=np.arange(len(item_name_list)) item_price=price_per_item['item_price'].tolist() plt.bar(x_pos, item_price, align='center') plt.ylabel('item price($)') plt.title('Distribution of item price') plt.show() # 아이템 가격 히스토그램을 출력합니다. plt.hist(item_price) plt.ylabel('counts') plt.title('Histogram of item price') plt.show()
가장 비싼 주문에서 아이템이 총 몇 개 팔렸는지 구하기¶
이 질문에서도 마찬가지로, order_id에 그룹별 합계 연산을 적용합니다. 그리고 item_price를 기준으로 sort_values를 반환하면 가장 비싼 주문순으로 연산 결과를 얻을 수 있습니다. 다음 결과에 서는 가장 비싼 주문에서 23개의 아이템을 주문한 것을 알 수 있습니다.
가장 비싼 주문에서 아이템이 총 몇 개 팔렸는지 구하기¶
In [16]:# 가장 비싼 주문에서 아이템이 총 몇 개 팔렸는지를 계산합니다. chipo.groupby('order_id').sum().sort_values(by='item_price', ascending=False)[:5]
Out[16]:quantity item_price order_id 926 23 205.25 1443 35 160.74 1483 14 139.00 691 11 118.25 1786 20 114.30 'Veggie Salad Bowl'이 몇 번 주문되었는지 구하기¶
이번에는 특정 아이템인 Veggie Salad Bowl'이 몇번이나 주문되었는지 알아보겠습니다. 이를 위해 chipo[chipo['item_name']=="Veggie Salad Bowl"]으로 필터링한 뒤, drop_duplicates()라는 함수를 사용합니다. 이는 한 주문 내에서 item_name이 중복 짐계된 경우를 제거해주기 위함입니다.
그리고 최종 결과인 chipo_salad의 길이를 출력하면 Veggie Salad Bowl이 데이터 내에서 몇 번이나 주문되었는지 구할 수 있습니다. 출력 결과, Veggie Salad Bowl은 총 18번 주문된 것을 알수 있습니다.'Veggie Salad Bowl'이 몇 번 주문되었는지 구하기¶
In [17]:# 'Veggie Salad Bowl'이 몇 번 주문되었는지를 계산합니다. chipo_salad=chipo[chipo['item_name']=="Veggie Salad Bowl"] # 한 주문 내에서 중복 집계된 item_name을 제거합니다. chipo_salad = chipo_salad.drop_duplicates(['item_name', 'order_id']) print(len(chipo_salad)) chipo_salad.head(5)
18
Out[17]:order_id quantity item_name choice_description item_price 186 83 1 Veggie Salad Bowl [Fresh Tomato Salsa, [Fajita Vegetables, Rice,... 11.25 295 128 1 Veggie Salad Bowl [Fresh Tomato Salsa, [Fajita Vegetables, Lettu... 11.25 455 195 1 Veggie Salad Bowl [Fresh Tomato Salsa, [Fajita Vegetables, Rice,... 11.25 496 207 1 Veggie Salad Bowl [Fresh Tomato Salsa, [Rice, Lettuce, Guacamole... 11.25 960 394 1 Veggie Salad Bowl [Fresh Tomato Salsa, [Fajita Vegetables, Lettu... 8.75 'Chicken Bowl'을 2개 이상 주문한 주문 횟수 구하기¶
비슷한 방법으로 'Chicken Bowl'을 2개 이상 주문한 주문 횟수를 구해봅시다. 먼저'Chicken Bowl'을 주문한 데이터만을 필터링한 뒤, 데이터프레임에서 quantity가 2 이상인 것을 선택하면 이결과가 'Chicken Bowl'을 2개이상 주문한 주문 횟수를 의미합니다. 2개 이상으로 필터링을 적용한 출력 결과는 다음과 같습니다.
'Chicken Bowl'을 2개이상 주문한 주문 횟수 구하기¶
In [18]:# "Chicken Bowl"을 2개 이상 주문한 주문 횟수를 구합니다. chipo_chicken=chipo[chipo['item_name']=="Chicken Bowl"] chipo_chicken_result=chipo_chicken[chipo_chicken['quantity']>=2] print(chipo_chicken_result.shape[0])
33
표로 정리하는 데이터 분석¶
- 데이터 탐색 질문 : 해당 피처 : 인사이트
- 가장 많이 주문된 아이템 : item_name : Chicken Bowl이 가장 인기 있는 아이템으로 나타남.
- 주분된 전체 아이템 종류 : item_name : 데이터셋에 총 50개의 주문된 아이템이 존재함.
- 아이템당 주문된 총 개수 : item_name : 50개 중, 상위8개 정도의 아이템에 주문이 집중됨.
- 주문당 평균 계산 급액 : item_name : 평균은 약 18, 표준편차는 11로 나타남. 25에서75%에 해당하는 구간이 12~21이며 최대값이 200을 넘는 것으로 보아. 소수의 주문을 제외하면 대부분 평균 근처의 계산 금액을 보임. 표준편차 11은 예외 처리를 통한 보정값을 계산할 여지가 있음.
- 각 아이템의 대략적인 가격 : item_price : 아이템의 판매 가격은 대부분 2~4, 혹은 6에서8 달러 정도임.
1.3 구가별 음주 데이터 분석하기¶
두 번째 예제에서는 국가별 음주 데이터를 활용하여 탐색적 데이터 분석을 진행합니다. 이를 통해 데이터 분석 라이브러리의 사용법과 탐색적 데이터 분석의 과정에 조금 더 익숙해지는 것을 목표로합니다. 이번 예제에 사용할 데이터인 drinks.csv 역시 python-data-analysis/data 폴더에 저장되어 있습니다.
Chapter 01 폴더 안의 02-drinks-eda.pnyd 파일을 실행하여 예제의 코드를 실행하거나 새로운 노트북 파엘에서 다음에 학습할 코드들을 실해보기 바랍니다.분석결과 : 대한민국은 술을 얼마나 독하게 마시는 나라일까?
step1 탐색 : 데이터의 기초 정보 살펴보기¶
이번 데이터셋을 이루고 있는 피처는 다음과 같습니다.
- country : 국가정보
- beer_servings : beer 소비량
- spirit_servings : spirit 소비량
- wine_servings : wine 소비량
- total_litres_of_pure_alcohol : 총 알코올 소비량
- continent : 국가의 대륙 정보
이 중에서 먼저 info() 함수로 데이터의 기초적인 정보를 살펴봅니다. 총 193개의 데이터가 있으며, country와 continent를 제외한 피처들은 수치형 피처로 구성되어 있다는 사실을 알 수 있습니다. 그리고 continent 피처는 23개의 결측값이 존재합니다.
drinks 데이터셋의 기초 정보 출력하기¶
In [19]:# -*- coding: utf-8 -*- import pandas as pd import numpy as np import matplotlib.pyplot as plt file_path = 'data/drinks.csv' drinks = pd.read_csv(file_path) # read_csv() 함수로 데이터를 데이터 프레임 형태로 불러옵니다. print(drinks.info()) drinks.head(10)
<class 'pandas.core.frame.DataFrame'> RangeIndex: 193 entries, 0 to 192 Data columns (total 6 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 country 193 non-null object 1 beer_servings 193 non-null int64 2 spirit_servings 193 non-null int64 3 wine_servings 193 non-null int64 4 total_litres_of_pure_alcohol 193 non-null float64 5 continent 170 non-null object dtypes: float64(1), int64(3), object(2) memory usage: 9.2+ KB None
Out[19]:country beer_servings spirit_servings wine_servings total_litres_of_pure_alcohol continent 0 Afghanistan 0 0 0 0.0 AS 1 Albania 89 132 54 4.9 EU 2 Algeria 25 0 14 0.7 AF 3 Andorra 245 138 312 12.4 EU 4 Angola 217 57 45 5.9 AF 5 Antigua & Barbuda 102 128 45 4.9 NaN 6 Argentina 193 25 221 8.3 SA 7 Armenia 21 179 11 3.8 EU 8 Australia 261 72 212 10.4 OC 9 Austria 279 75 191 9.7 EU 나머지 피처의 수치적 정보를 살펴보기 위해 describe() 함수를 실행해보면 결과는 아래와 같습니다.
In [20]:drinks.describe()
Out[20]:beer_servings spirit_servings wine_servings total_litres_of_pure_alcohol count 193.000000 193.000000 193.000000 193.000000 mean 106.160622 80.994819 49.450777 4.717098 std 101.143103 88.284312 79.697598 3.773298 min 0.000000 0.000000 0.000000 0.000000 25% 20.000000 4.000000 1.000000 1.300000 50% 76.000000 56.000000 8.000000 4.200000 75% 188.000000 128.000000 59.000000 7.200000 max 376.000000 438.000000 370.000000 14.400000 Step 2 인사이트의 발견: 탐색과 시각화하기¶
다음으로 피처 간의 상관 관계를 살펴봅시다. 피처 간의 상관 관계를 통계적으로 탐색하는 방법은 크게 두 가지입니다. 첫 번째 방법은 피처가 2개일 때의 상관 계수를 계산하는 단순 상관 분석 방법이며, 두번째 방법은 대상 피처가 여러 개일 때 상호 간의 연관성을 분석하는 다중 상관 분석입니다. 이 중, 우리가 적용해볼 방법은 첫 번째 방법인 단순 상관 분석입니다.
상관 분석¶
상관 분석이란 두 변수 간의 선형적 관계를 상관 계수로 표현하는 것입니다. 상관 계수를 구하는 것은 공분산의 개념을 포함합니다. 공분산은 2개의 확률 변수에 대한 상관 정도로, 2개의 변수 중 하나의 값이 상승하는 경향을 보일 때 다른 값도 상승하는 경향을 수치로 나타낸 것입니다. 하지만 공분산만으로 두 확률 변수의 상관 관계를 구한다면 두 변수의 단위 크기에 영향을 받을 수 있습니다. 따라서 이를 -1과 1사이의 값으로 변환합니다. 이를 상관 계수라 합니다. 만약 상관 계수가 1에 가깝다면 서로 강한 양의 상관 관계가 있는 것이고, -1에 가깝다면 음의 상관 관계가 있는 것입니다.
상관 관계를 살펴볼 대상은 beer_servings, wine_servings, spirit_servungs, total_litres_of_pure_alcohol 이렇게 4개의 피처입니다. 이 피처는 술의종류만 다를 뿐, 결국에는 비슷한 의미를 가지는 피처들이기 때문입니다.
먼저 맥주와 와인 소비량의 상관 관계를 알아봅시다. 아래 코드처럼 데이터 프레임에서 두 피처를 선택한 뒤, corr() 함수를 적용합니다. 이를 통해 피처 간의 상관 계수를 matrix의 형태로 출력할 수 있습니다. 출력 결과, beer_servings와 wine_servings 두 피처 간의 상관 계수는 0.52 정도로 나타났습니다.In [21]:# beer_servings, wine_servings 두 피처 간의 상관 계수를 꼐산합니다. # pearson은 상관 계수를 구하는 계산 방법 중 하나를 의미하며, 가장 널리 쓰이는 방법입니다. corr =drinks[['beer_servings', 'wine_servings']].corr(method ='pearson') print(corr)
beer_servings wine_servings beer_servings 1.000000 0.527172 wine_servings 0.527172 1.000000
이제 모든 피처들을 각각 1대 1로 비교하여 살펴봅시다. 아래 실행 결과는 4개 피처에 corr()함수를 적용한 상관 계수 행렬을 출력한 것입니다.
여러 피처의 상관 관계 분석하기¶
In [22]:# 피처간의 상관 계수 행렬을 구합니다. cols=['beer_servings', 'spirit_servings', 'wine_servings', 'total_litres_of_pure_alcohol'] corr=drinks[cols].corr(method='pearson') print(corr)
beer_servings spirit_servings wine_servings \ beer_servings 1.000000 0.458819 0.527172 spirit_servings 0.458819 1.000000 0.194797 wine_servings 0.527172 0.194797 1.000000 total_litres_of_pure_alcohol 0.835839 0.654968 0.667598 total_litres_of_pure_alcohol beer_servings 0.835839 spirit_servings 0.654968 wine_servings 0.667598 total_litres_of_pure_alcohol 1.000000
이를 조금 더 쉽게 실행하기 위해 'heatmap', 'pairplot'이라는 기법을 사용해봅시다. 파이썬의 seaborn이라는 시각화 라이브러리를 활용하여 이 2개 기법을 사용할 수 있습니다.
코드는 매우 간답합니다. heatmap의 경우 corr.values를, pairplot의 경우 데이터 프레임을 파라미터로 넣어줍니다. 그 외에도 그래프의 디자인과 관련된 몇 가지 파라미터를 설정할 수 있습니다.
In [23]:import seaborn as sns import matplotlib.pyplot as plt # corr 행렬 히트맵을 시각화합니다. cols_view=['beer', 'spirit', 'wine', 'alcohol'] # 그래프 출력을 위한 cols 이름을 축약합니다. sns.set(font_scale=1.5) hm=sns.heatmap(corr.values, cbar=True, annot=True, square=True, fmt='.2f', annot_kws={'size':15}, yticklabels=cols_view, xticklabels=cols_view) plt.tight_layout() plt.show() # 시각화 라이브러리를 이용한 피처 간의 산점도 그래프를 출력합니다. sns.set(style='whitegrid', context='notebook') sns.pairplot(drinks[['beer_servings', 'spirit_servings','wine_servings', 'total_litres_of_pure_alcohol']], height=2.5) plt.show()
Step 3 탐색적 분석: 스무고개로 개념적 탐색 분석하기¶
본격적인 탐색적 분석에 들어가기에 앞서 continent 피처에 존재하는 결측 데이터를 처리해봅시다. 대륙에 대한 정보가 없는 국가를 'Others', 줄여서 'OT'라는 대륙으로 새롭게 정의하겠습니다. 이를 처리하는 코드는 다음과 같습니다.. fillna() 함수를 사용하여 drinks 데이터 프레임의 continent 피처의 결측값을 OT로 채워줍니다.
결측 데이터 전처리하기¶
In [24]:# 결측 데이터를 처리합니다: 기타 대륙으로 통합 'OT' drinks['continent']=drinks['continent'].fillna('TO') drinks.head(10)
Out[24]:country beer_servings spirit_servings wine_servings total_litres_of_pure_alcohol continent 0 Afghanistan 0 0 0 0.0 AS 1 Albania 89 132 54 4.9 EU 2 Algeria 25 0 14 0.7 AF 3 Andorra 245 138 312 12.4 EU 4 Angola 217 57 45 5.9 AF 5 Antigua & Barbuda 102 128 45 4.9 TO 6 Argentina 193 25 221 8.3 SA 7 Armenia 21 179 11 3.8 EU 8 Australia 261 72 212 10.4 OC 9 Austria 279 75 191 9.7 EU 이번에는 전체 대륙 중에서 OT가 차지하는 비율이 얼마나 되는지를 파이차트로 확인해봅시다. 아래코드는 plt.pie()함수를 이용한 파이차트 출력 방법입니다.
파이차트로 시각화하기¶
In [25]:labels=drinks['continent'].value_counts().index.tolist() fracs1=drinks['continent'].value_counts().values.tolist() explode=(0,0,0,0.25,0,0) plt.pie(fracs1,explode=explode, labels=labels, autopct='%.0f%%', shadow=True) plt.title('null data to \'OT\'') plt.show()
이제 본격적으로 데이터와 스무고개를 하기 위한 질문을 하나씩 정의해봅시다.
대륙별 spirit_servings의 통계적 정보는 어느 정도일까?¶
다음 코드는 agg() 함수를 사용하여 대륙 단위로 분석을 수행합니다. agg() 함수는 apply()함수와 거의 동일한 기능을 하지만, apply()에 들어가는 함수 파라미터를 병렬로 설정하여 그룹에대한 여러가지 연산 결과를 동시에 얻을 수 있는 함수입니다. 대륙별'spitit_servings'의 통계적 정보를 구하기위해서는 agg에 ['mean'.'min','max','sum'] 파라미터를 입력하는 것만으로도 간단히 탐색이 가능합니다.
agg() 함수를 이용해 대륙별로 분석하기¶
In [26]:# 대륙별 spirit_servings의 평균, 최소, 최대, 합계를 계산합니다. result=drinks.groupby('continent').spirit_servings.agg(['mean','min','max','sum']) result.head()
Out[26]:mean min max sum continent AF 16.339623 0 152 866 AS 60.840909 0 326 2677 EU 132.555556 0 373 5965 OC 58.437500 0 254 935 SA 114.750000 25 302 1377 전체 평균보다 알코올을 섭취하는 대륙은 어디일까?¶
전체 평균보다 많은 알코올을 섭취하는 대륙을 탐색할 때는 apply()나 agg() 함수없이도 mean()함수만을 이용한 탐색을 수행할 수 있습니다.
In [27]:# 전체 평균보다 많은 알코올을 섭취하는 대륙을 구합니다. total_mean=drinks.total_litres_of_pure_alcohol.mean() continent_mean=drinks.groupby('continent')['total_litres_of_pure_alcohol'].mean() continent_over_mean=continent_mean[continent_mean >= total_mean] print(continent_over_mean)
continent EU 8.617778 SA 6.308333 TO 5.995652 Name: total_litres_of_pure_alcohol, dtype: float64
평균 beer_servings가 가장 높은 대륙은 어디일까?¶
그리고 mean() 함수만을 이용한 탐색에 idxmax() 함수를 적용하면 평균 'beer_servungs'가 가장 높은 대륙이 어디인지 찾을 수 있씁니다. idxmax()는 시리즈 객체에서 값이 가장 큰 index를 반환하는 기능을 수행합니다.
In [28]:# 평균 beer_servings가 가장 높은 대륙을 구합니다. beer_continent=drinks.groupby('continent').beer_servings.mean().idxmax() print(beer_continent)
EU
위의 두 가지 질문에 대한 탐색을 통해 우리는 AF, AS, EU, OC, OT대륙 중 ES, OT, AS만이 평균보다 많이 알코올을 섭취하는 대륙인 것을 알 수 있었고, 또한 맥주를 가장 좋아하는 대륙은 유렵이라는 결과를 확인할 수 있었습니다.
시각화¶
아래 코드는 이 결과를 그래프로 시각화한 것입니다. 코드를 천천히 살펴보고, 부분별로 실행하며 막대 그래프의 사용법을 익혀봅시다.
분석결과를 시각화하기¶
In [29]:# 대륙별 spirit_servings의 평균, 최소, 최대, 합계를 시각화합니다. n_groups=len(result.index) means=result['mean'].tolist() mins=result['min'].tolist() maxs=result['max'].tolist() sums=result['sum'].tolist() index=np.arange(n_groups) bar_width=0.1 rects1= plt.bar(index, means, bar_width, color='r',label='Mwan') rects2= plt.bar(index + bar_width, mins, bar_width, color='g', label='Min') rects3= plt.bar(index + bar_width*2, maxs,bar_width, color='b', label='Max') rects3= plt.bar(index + bar_width*2, sums,bar_width, color='y', label='Sum') plt.xticks(index, result.index.tolist()) plt.legend() plt.show()
In [33]:# 대륙별 total_litres_of_pure_alcohol을 시각화 합니다. continents=continent_mean.index.tolist() continents.append('mean') x_pos=np.arange(len(continents)) alcohol=continent_mean.tolist() alcohol.append(total_mean) bar_list=plt.bar(x_pos, alcohol, align='center',alpha=0.5) bar_list[len(continents)-1]. set_color('r') plt.plot([0.,6],[total_mean, total_mean],"k--") plt.xticks(x_pos,continents) plt.ylabel('total_litres_of_pure_alcohol') plt.title('total_litres_of_pure_alcohol by Continent') plt.show()
In [34]:#대륙별 beer_servings를 시각화합니다. beer_group=drinks.groupby('continent')['beer_servings'].sum() continents=beer_group.index.tolist() y_pos=np.arange(len(continents)) alcohol=beer_group.tolist() bar_list=plt.bar(y_pos, alcohol, align='center',alpha=0.5) bar_list[continents.index("EU")].set_color('r') plt.xticks(y_pos, continents) plt.ylabel('beer_servings') plt.title('beer_servings by Continent') plt.show()
Step 4 통계적 분석: 분석 대상 간의 통계적 차이 검정하기¶
지금까지는 두 피처 간의 상관성을 계산하거나 혹은 그룹 단위로 나누어 수치 정보를 살펴보는 방식의 데이터 분석을 알아보았습니다. 이러한 분석은 데이터에서 인사이트를 발견하는 데 있어서 매우 유용한 방법입니다. 하지만 이는 분석가의 주관에 따라 도출된 내용이기 때문에 분석 자체의 타장성을 증명하기에는 한계가 있습니다. 따라서 분석 결과에 타당성을 부여하기 위해 통계적으로 차이를 검정하는 과정이 필요합니다. 그 중 가장 기본적인 방법인 t-test를 통해 분석 대상 간의 통계적 차이를 검정하는 방법을 알아봅시다.
t-test¶
t-test란 두 집단 간 평균의 차이에 대한 검정 방법으로, 모집단의 평균 등과 같이 실제 정보를 모를 때 현재의 데이터만으로 두 집단의 차이에 대해 검정할 수 있는 방법입니다. 단, t-test는 검정 대상인 두 집단의 데이터 개수가 비슷하면서 두 데이터가 정규 분포를 보이는 경우에 신뢰도가 높은 검정 방식입니다.
파이썬에서는 scipy라는 라이브러리를 활용하여 두 집단 간의 t-test를 검정할 수 있습니다. 아래 코드는 t-test를 적용하는 아주 간단한 예제입니다. ttest_ind() 함수에 두 집단의 시리즈 데이터를 넣는 것으로 검정의 결과를 확인할 수 있는데, 이 함수의 파라미터인 equal_var는 t-test의 두가지 방법 중에 하나를 선택하는 것입니다. 첫 번째는 두 집단의 분산이 같은 경우, 그리고 두 번째는 두 집단의 분산이 같지 않은 경우를 가정한 것입니다.
아프리카와 유럽 간의 맥주 소비량 차이 검정하기¶
In [40]:# 아프리카와 유럽 간의 맥주 소비량 차이를 검정합니다. africa=drinks.loc[drinks['continent']=='AF'] europe=drinks.loc[drinks['continent']=='EU'] from scipy import stats tTestResult=stats.ttest_ind(africa['beer_servings'], europe['beer_servings']) tTestResultDiffVar=stats.ttest_ind(africa['beer_servings'],europe['beer_servings'], equal_var=False) print("The t-statistic and p-value assuming equal variances is %.3f and %.3f"%tTestResult) print("The t-statistic and p-value not assuming equal variances is %.3f and %.3f % tTestResultDiffVar")
The t-statistic and p-value assuming equal variances is -7.268 and 0.000 The t-statistic and p-value not assuming equal variances is %.3f and %.3f % tTestResultDiffVar
실행 결과에 등장하는 t-statistic은 t-test의 검정 통계량을 의미하는 것으로, 함께 출력되는 p-value와 연관 지어 해석해야 합니다. p-value는 가설이 얼마나 믿을만한 것인지를 나타내는 지표러, 데이터를 새로 샘플링했을 때 귀무 가설이 맞다는 전제 하에 현재 나온 통계값 이상이 나올 확률이라고 정의할 수 있습니다. 만약 p-value가 너무 낮으면 귀무 가설이 일어날 확률이 너무 낮기 때문에 귀무 가설을 기각하게 됩니다. 보통 그 기준은 0.05나 0.01을 기준으로 하며, 이를 p-valie(유의확률)이라고 합니다. 귀무 가설이란 처음부터 버릴 것을 예상하는 가설이며, 가설이 맞지 않다는 것을 증명하기 위해 수립하는 가설입니다. 그리고 반대되는 것을 대립 가설이라고 부르며, 귀무 가설이 거짓인 경우에 대안적으로 참이 되는 가설을 의미합니다.
위의 실행 결과에서는 등분산을 가정한 케이스와 가정하지 않은 케이스 보두 p-value가 0.000 이하로 나타났습니다. t-test의 귀무 가설은 '두 집단이 평균이 같다'이고 이 귀무 가설은 기각되었습니다. 따라서'아프리카와 유럽 대륙 간의 맥주 소비량 차이'는 통계적으로 유의미하다는 결론을 내릴 수 있습니다. 이는 대립 가설인' 두 집단의 평균이 다르다'를 채택한 것입니다. 하지만 두 집단의 데이터는 크기도 다르고, 각각의 크기 또한 크지 않기 때문에 실제로 통계적인 의미를 가지는 검정이라고 보기엔 어렵습니다. 만약 통계적 분석을 하기에 좋은 조건인 경우라면 이러한 방법을 사용할수 있다는 것만 알아둡시다.
드디어 이번 절의 처음에 나왔던 주제인'대한민국은 얼마나 독하게 술을 마시는 나라일까?'에 대한 탐색 코드를 살펴볼 차례입니다. 이를 판단하는 기준으로, alcohol_rate 피처를 생성합니다. 이 피처는 total_litres_of_pure_alcohol 피처를 모든 술의 총 소비량으로 나눈 것입니다. 그리고 alcohol_rate는 sort_values() 함수를 사용하여 국가를 기준으로 정렬합니다.'대한민국은 얼마나 술을 독하게 마시는 나라일까?'에 대한 탐색 코드 살펴보기¶
In [42]:# total_servings 피처를 생성합니다. drinks['total_servings']=drinks['beer_servings']+drinks['wine_servings']+drinks['spirit_servings'] #술 소비량 대비 알코올 비율 피처를 생성합니다. drinks['alcohol_rate']=drinks['total_litres_of_pure_alcohol']/drinks['total_servings'] drinks['alcogol_rate']=drinks['alcohol_rate'].fillna(0) # 순위 정보를 생성합니다. country_with_rank=drinks[['country','alcohol_rate']] country_with_rank=country_with_rank.sort_values(by=['alcohol_rate'], ascending=0) country_with_rank.head(5)
Out[42]:country alcohol_rate 63 Gambia 0.266667 153 Sierra Leone 0.223333 124 Nigeria 0.185714 179 Uganda 0.153704 142 Rwanda 0.151111 이 결과를 토대로 시각화를 수행한 결과는 다음과 같습니다. x_pos=np.arange(len(country_list))를 통해 그래프의 x축에 해당하는 범위를 생성하고, rank=country_with_rank.alcohol_rate.tolist()를 통해 alcohol_rate순으로 정렬된 데이터에서 alcohol_rate 값을 생성하였습니다.
국가별 순위 정보를 시각화하기¶
In [48]:# 국가별 순위 정보를 그래프로 시각화합니다. country_list=country_with_rank.country.tolist() x_pos=np.arange(len(country_list)) rank=country_with_rank.alcohol_rate.tolist() bar_list=plt.bar(x_pos, rank) bar_list[country_list.index("South Korea")].set_color('r') plt.ylabel('alcohol rate') plt.title('alcohol rate') plt.title('liquor drink rank by contry') plt.axis([0,200,0,0.3]) korea_rank=country_list.index("South Korea") korea_alc_rate=country_with_rank[country_with_rank['country']=='South Korea']['alcohol_rate'].values[0] plt.annotate('South Korea : '+str(korea_rank+1), xy=(korea_rank,korea_alc_rate), xytext=(korea_rank +10, korea_alc_rate +0.05), arrowprops=dict(facecolor='red',shrink=0.05)) plt.show()
표로 정리하는 데이터 분석¶
- 데이터 탐색 질문 : 핵심 내용 : 인사이트
- 각의 피처는 서로 어떤 상관 관계를 가지고 있는가? : 모든 연속형 피처의 상관 분석 : 대부분의 국가의 총 알코올 소비량은 맥주 소비량에 영향을 받을 확률이 높음. 또한 대부분의 국가에서는 맥주가 가장 많이 소비되는 술이라는 해석도 가능함.
- 평균 맥주 소비량이 가장 높은 대륙은? : 모든 행을 그룹 단위로 분석 : 유럽이 가장 맥주 소비량이 높은. 대륙별로 상이한 차이가 있다는 것을 발견함.
- 술 소비량 대비 알코올 비율 피처 생성하기 : 새로운 분석 피처 생성 : 술 소비량 대비 알코올 비율이라는 새로운 피처로부터 술을 독하게 마시는 정도의 국가별 차이를 관찰 가능함.
- 아프리카와 유럽 간의 맥주 소비량 차이 검정하기 : 통계적 차이 검정 : t-test 분석 결과. 아프리카와 유럽 간의 맥주 소비량은 통계적으로 유의미한 차이를 보임 (단, 이 예제는 그룹 간의 데이터 크기가 매우 다르고, 정규분포를 띤다는 가정을 할 수 없기 때문에 신뢰할 만한 정보라고 할수 없음)
출처 : "이것이 데이터 분석이다 with 파이썬"
'이것이 데이터 분석이다 with 파이썬' 카테고리의 다른 글
chapter-3.3 미래에 볼 영화의 평점 예측하기 (0) 2021.10.13 chapter-5.2 구매 데이터를 분석하여 상품 추천하기 (0) 2021.10.11 chapter_4.1 타이타닉 생존자 가려내기 (0) 2021.10.06 chapter-3.2 비트코인 시세 예측하기 (0) 2021.09.30 chapter-3.1 프로야구 선수의 다음 해 연봉 예측하기 (0) 2021.09.30