앎을 경계하기

Machine Learning/Statistics

파이썬 데이터분석 실무 테크닉 100 - 1장

양갱맨 2020. 11. 30. 17:51

 

 

 

 

파이썬 데이터 분석 실무 테크닉 100은 주어진 데이터에 적용할 여러 라이브러리의 함수 사용법을 설명하는 책들과 달리, 실무에서 데이터가 주어졌을 때 가장 먼저 해야할 일과 이후 순차적으로 분석방법에 대해 설명한다.

01장 웹에서 주문수를 분석하는 테크닉 10

목표 : 어떤 기업 쇼핑몰 사이트의 상품 주문 수의 추세를 분석하여 판매량 개선의 방향 찾기.

쇼핑몰 사이트는 비교적 깨끗한 데이터인 경우가 많다. 쇼핑몰 사이트는 매출 추세뿐만 아니라 언제, 누가 구입했는지 등, 상세 데이터가 많을 수록 깊게 분석이 가능하다. 그러나 현장에서 데이터를 관리할 때, 한 곳에서 관리되지 않는 것이 일반적이다. 이러한 경우 데이터를 연결하는 작업이 필요할 때도 있다.

전제조건

  • 쇼핑몰 사이트의 데이터를 다룬다.
  • 주요 품목은 컴퓨터이다.
  • 가격대별 5개의 상품이 존재함.
  • 데이터는 4종류의 6개 데이터이다.
    • customer_master.csv : 고객 정보 - 회원가입 시 입력하는 데이터가 저장된다.
    • item_master.csv : 상품 정보 - 상품명과 가격이 포함되어 있다.
    • transaction_1.csv : 구매내역 - 언제, 누가, 얼마나 구매했는지에 대한 정보
    • transaction_2.csv : 구매내역 - 언제, 누가, 얼마나 구매했는지에 대한 정보(transaction_1의 분할 데이터)
    • transaction_detail_1.csv : 구매내역 상세 데이터 - 어떤 상품을 몇 개 샀는지와 같은 상세 정보 포함
    • transaction_detail_2.csv : 구매내역 상세 데이터 - 어떤 상품을 몇 개 샀는지와 같은 상세 정보 포함(transaction_detail_1의 분할 데이터)
 

001 데이터 읽기

In [2]:
import pandas as pd
customer_master = pd.read_csv('./customer_master.csv')
customer_master.head()
Out[2]:
  customer_id customer_name registration_date email gender age birth pref
0 IK152942 김서준 2019-01-01 0:25 hirata_yuujirou@example.com M 29 1990-06-10 대전광역시
1 TS808488 김예준 2019-01-01 1:13 tamura_shiori@example.com F 33 1986-05-20 인천광역시
2 AS834628 김도윤 2019-01-01 2:00 hisano_yuki@example.com F 63 1956-01-02 광주광역시
3 AS345469 김시우 2019-01-01 4:48 tsuruoka_kaoru@example.com M 74 1945-03-25 인천광역시
4 GD892565 김주원 2019-01-01 4:54 oouchi_takashi@example.com M 54 1965-08-05 울산광역시
In [3]:
item_master = pd.read_csv('./item_master.csv')
item_master.head()
Out[3]:
  item_id item_name item_price
0 S001 PC-A 50000
1 S002 PC-B 85000
2 S003 PC-C 120000
3 S004 PC-D 180000
4 S005 PC-E 210000
In [11]:
transaction_1 = pd.read_csv('./transaction_1.csv')
transaction_1.head()
Out[11]:
  transaction_id price payment_date customer_id
0 T0000000113 210000 2019-02-01 01:36:57 PL563502
1 T0000000114 50000 2019-02-01 01:37:23 HD678019
2 T0000000115 120000 2019-02-01 02:34:19 HD298120
3 T0000000116 210000 2019-02-01 02:47:23 IK452215
4 T0000000117 170000 2019-02-01 04:33:46 PL542865
In [12]:
transaction_detail_1 = pd.read_csv('./transaction_detail_1.csv')
transaction_detail_1.head()
Out[12]:
  detail_id transaction_id item_id quantity
0 0 T0000000113 S005 1
1 1 T0000000114 S001 1
2 2 T0000000115 S003 1
3 3 T0000000116 S005 1
4 4 T0000000117 S002 2
 

각 데이터셋 파악

  1. customer_master에는 고객의 성별, 나이, 주소, 이메일, 이름, 가입일자 등
  2. item_master에는 상품아이디, 상품명, 상품가격
  3. transcation에는 고객 아이디, 가격, 구입 일자 등
  4. transaction_detail에는 상품아이디, 수량, 상세 아이디 등

매출과 관련된 데이터를 생각해보자. 상세 데이터가 매출과 직결된다. 왜냐하면, 상세 데이터에 각 상품 주문 수량이 포함되기 때문이다.

1차적으로 transaction 관련 데이터셋들이 1, 2로 분할되어 있기 때문에 결합시켜주는 작업이 필요하다.

002 데이터 결합

In [15]:
transaction_2 = pd.read_csv('./transaction_2.csv')
transaction = pd.concat([transaction_1, transaction_2])
transaction.head()
Out[15]:
  transaction_id price payment_date customer_id
0 T0000000113 210000 2019-02-01 01:36:57 PL563502
1 T0000000114 50000 2019-02-01 01:37:23 HD678019
2 T0000000115 120000 2019-02-01 02:34:19 HD298120
3 T0000000116 210000 2019-02-01 02:47:23 IK452215
4 T0000000117 170000 2019-02-01 04:33:46 PL542865
In [16]:
print(transaction_1.shape, transaction_2.shape, transaction.shape)
 
(5000, 4) (1786, 4) (6786, 4)
In [17]:
transaction_detail_2 = pd.read_csv('transaction_detail_2.csv')
transaction_detail = pd.concat([transaction_detail_1, transaction_detail_2])
transaction_detail.head()
Out[17]:
  detail_id transaction_id item_id quantity
0 0 T0000000113 S005 1
1 1 T0000000114 S001 1
2 2 T0000000115 S003 1
3 3 T0000000116 S005 1
4 4 T0000000117 S002 2
In [19]:
print(transaction_detail_1.shape, transaction_detail_2.shape, transaction_detail.shape)
 
(5000, 4) (2144, 4) (7144, 4)
 

003 매출 관련 데이터 결합하기

데이터를 조인할 때, 기준이 되는 데이터를 정확하게 결정하고 어떤 컬럼을 키로 조인할지 생각해야한다.

가장 상세한 데이터인 transaction_detail을 기준 데이터로 결정한다.

데이터셋 조인 시, 부족한 데이터 컬럼이 무엇인가공통되는 데이터 컬럼은 무엇인가를 생각한다.

이번에 추가할 데이터는 transaction의 구입 일자와 구매 고객 아이디이다.

transaction의 price는 한 번 구매 시 합계 금액이다. transaction_detail의 quantity와 item_master의 item_price로부터 계산된 것.

=transaction[price] = transaction_detail[quantity]*item_master[item_price]

공통 데이터 컬럼은 transaction_id이다.

In [21]:
join_data = pd.merge(transaction_detail, transaction[["transaction_id", "payment_date", "customer_id"]], on="transaction_id", how="left")
join_data.head()
Out[21]:
  detail_id transaction_id item_id quantity payment_date customer_id
0 0 T0000000113 S005 1 2019-02-01 01:36:57 PL563502
1 1 T0000000114 S001 1 2019-02-01 01:37:23 HD678019
2 2 T0000000115 S003 1 2019-02-01 02:34:19 HD298120
3 3 T0000000116 S005 1 2019-02-01 02:47:23 IK452215
4 4 T0000000117 S002 2 2019-02-01 04:33:46 PL542865
In [22]:
print(join_data.shape, transaction.shape, transaction_detail.shape)
 
(7144, 6) (6786, 4) (7144, 4)
 

004 마스터 데이터 결합

위에서 결합한 매출관련 데이터셋을 customer_masteritem_master 각각 결합한다.

두 데이터셋은 customer_id, item_id로 연결할 수 있다.

In [23]:
join_data = pd.merge(join_data, customer_master, on='customer_id', how="left")
join_data = pd.merge(join_data, item_master, on='item_id', how="left")
join_data.head()
Out[23]:
  detail_id transaction_id item_id quantity payment_date customer_id customer_name registration_date email gender age birth pref item_name item_price
0 0 T0000000113 S005 1 2019-02-01 01:36:57 PL563502 김태경 2019-01-07 14:34 imoto_yoshimasa@example.com M 30 1989-07-15 대전광역시 PC-E 210000
1 1 T0000000114 S001 1 2019-02-01 01:37:23 HD678019 김영웅 2019-01-27 18:00 mifune_rokurou@example.com M 73 1945-11-29 서울특별시 PC-A 50000
2 2 T0000000115 S003 1 2019-02-01 02:34:19 HD298120 김강현 2019-01-11 8:16 yamane_kogan@example.com M 42 1977-05-17 광주광역시 PC-C 120000
3 3 T0000000116 S005 1 2019-02-01 02:47:23 IK452215 김주한 2019-01-10 5:07 ikeda_natsumi@example.com F 47 1972-03-17 인천광역시 PC-E 210000
4 4 T0000000117 S002 2 2019-02-01 04:33:46 PL542865 김영빈 2019-01-25 6:46 kurita_kenichi@example.com M 74 1944-12-17 광주광역시 PC-B 85000
 

각 데이터셋 별 컬럼

imageimageimageimageimage

transaction, transaction_detail data를 결합할 때, price가 포함되지 않았음에 주의한다.

005 필요한 컬럼 만들기

In [31]:
join_data['price'] = join_data['quantity']*join_data['item_price']
join_data[['price', 'quantity', 'item_price']].head(10)
Out[31]:
  price quantity item_price
0 210000 1 210000
1 50000 1 50000
2 120000 1 120000
3 210000 1 210000
4 170000 2 85000
5 120000 1 120000
6 180000 1 180000
7 50000 1 50000
8 210000 1 210000
9 85000 1 85000
 

006 데이터 검산

잘못된 데이터를 제공하는 것은 회사 경영에 막대한 영향을 끼친다.

따라서 데이터 결합 시 개수 확인은 신중하게 해야하며, 되도록 검산 가능한 데이터를 찾아 계산해야한다.

In [32]:
print(join_data['price'].sum())
print(transaction['price'].sum())
 
971135000
971135000
 

여기까지 데이터를 읽고 파악하는 과정을 진행하였다. 이제 데이터 분석을 적용한다.

007 각종 통계량 파악

데이터 분석을 할 때, 먼저 두 가지 숫자를 파악해야 한다.

  1. 결손치의 개수
  2. 전체를 파악할 수 있는 숫자감이다.
In [35]:
join_data.isnull().sum() # null인 데이터의 개수를 표현
Out[35]:
detail_id            0
transaction_id       0
item_id              0
quantity             0
payment_date         0
customer_id          0
customer_name        0
registration_date    0
email                0
gender               0
age                  0
birth                0
pref                 0
item_name            0
item_price           0
price                0
dtype: int64
In [36]:
join_data.describe() # 각 기준에 따라 통계치 표현
Out[36]:
  detail_id quantity age item_price price
count 7144.000000 7144.000000 7144.000000 7144.000000 7144.000000
mean 3571.500000 1.199888 50.265677 121698.628219 135937.150056
std 2062.439494 0.513647 17.190314 64571.311830 68511.453297
min 0.000000 1.000000 20.000000 50000.000000 50000.000000
25% 1785.750000 1.000000 36.000000 50000.000000 85000.000000
50% 3571.500000 1.000000 50.000000 102500.000000 120000.000000
75% 5357.250000 1.000000 65.000000 187500.000000 210000.000000
max 7143.000000 4.000000 80.000000 210000.000000 420000.000000
In [38]:
print(join_data['payment_date'].min())
print(join_data['payment_date'].max())
 
2019-02-01 01:36:57
2019-07-31 23:41:38
 

008 월별 데이터 집계

pandas의 dt를 사용하여 년, 월 추출을 한다.

In [42]:
join_data['payment_date'] = pd.to_datetime(join_data['payment_date'])
join_data['payment_month'] = join_data['payment_date'].dt.strftime("%Y%m")#년, 월로 표현
join_data[['payment_date','payment_month']].head()
Out[42]:
  payment_date payment_month
0 2019-02-01 01:36:57 201902
1 2019-02-01 01:37:23 201902
2 2019-02-01 02:34:19 201902
3 2019-02-01 02:47:23 201902
4 2019-02-01 04:33:46 201902
 

009 월별, 상품별 집계

groupby를 사용하여 집계 가능하다.

In [43]:
join_data.groupby(["payment_month","item_name"]).sum()[["price", "quantity"]]
Out[43]:
    price quantity
payment_month item_name    
201902 PC-A 24150000 483
PC-B 25245000 297
PC-C 19800000 165
PC-D 31140000 173
PC-E 59850000 285
201903 PC-A 26000000 520
PC-B 25500000 300
PC-C 19080000 159
PC-D 25740000 143
PC-E 64050000 305
201904 PC-A 25900000 518
PC-B 23460000 276
PC-C 21960000 183
PC-D 24300000 135
PC-E 64890000 309
201905 PC-A 24850000 497
PC-B 25330000 298
PC-C 20520000 171
PC-D 25920000 144
PC-E 58800000 280
201906 PC-A 26000000 520
PC-B 23970000 282
PC-C 21840000 182
PC-D 28800000 160
PC-E 63420000 302
201907 PC-A 25250000 505
PC-B 28220000 332
PC-C 19440000 162
PC-D 26100000 145
PC-E 71610000 341
In [44]:
#pivot table 사용 시 더 쉽게 볼 수 있다.
pd.pivot_table(join_data, index='item_name', columns='payment_month', values=['price', 'quantity'], aggfunc='sum')
Out[44]:
  price quantity
payment_month 201902 201903 201904 201905 201906 201907 201902 201903 201904 201905 201906 201907
item_name                        
PC-A 24150000 26000000 25900000 24850000 26000000 25250000 483 520 518 497 520 505
PC-B 25245000 25500000 23460000 25330000 23970000 28220000 297 300 276 298 282 332
PC-C 19800000 19080000 21960000 20520000 21840000 19440000 165 159 183 171 182 162
PC-D 31140000 25740000 24300000 25920000 28800000 26100000 173 143 135 144 160 145
PC-E 59850000 64050000 64890000 58800000 63420000 71610000 285 305 309 280 302 341
 

pivot_table은 행과 칼럼을 지정할 수 있다.

index에는 상품명, columns에는 구입월이 오도록 지정한다.

values에는 집계하고 싶은 컬럼들을 지정해준다.

aggfunc는 집계 방법을 의미한다.

결과 표를 보면, PC-E가 price(매출합)가 높지만 quantity(수량)에 있어서는 가장 싼 PC-A가 판매량이 가장 높다.

월별 추세에 따르면, 5월에 PC-B와 D는 매출액이 증가하였으나 가장 큰 매출을 차지하는 PC-E는 오히려 감소하는 것을 보인다. PC-E는 6, 7월에 매출이 크게 증가하였다.

 

010 상품별 매출 추이 가시화

수치 데이터는 변화를 한 번에 보기 어렵다.

따라서, 지금까지 살펴본 월별 및 상품별 매출 추이를 시각화하겠다.

In [71]:
graph_data = pd.pivot_table(join_data, values='price', index='payment_month', columns='item_name', aggfunc='sum')
graph_data.head()
Out[71]:
item_name PC-A PC-B PC-C PC-D PC-E
payment_month          
201902 24150000 25245000 19800000 31140000 59850000
201903 26000000 25500000 19080000 25740000 64050000
201904 25900000 23460000 21960000 24300000 64890000
201905 24850000 25330000 20520000 25920000 58800000
201906 26000000 23970000 21840000 28800000 63420000
In [70]:
import matplotlib.pyplot as plt
%matplotlib inline
In [73]:
for item in sorted(join_data['item_name'].unique()):
    plt.plot(list(graph_data.index), graph_data[item], label=item)
plt.legend()
Out[73]:
<matplotlib.legend.Legend at 0x1e3ae335b20>