데이터 사이언스 100번의 노크(구조화 데이터 처리편) – Python Part 2 (Q21 to Q40)의 해설입니다.
처음에
- 먼저 다음 셀을 실행합니다.
- 필요한 라이브러리를 가져오고 데이터베이스에서 데이터를 읽습니다(PostgreSQL).
- 사용할 것으로 예상되는 라이브러리는 다음 셀에서 가져옵니다.
- 사용하려는 다른 라이브러리가 있는 경우 install.packages()를 사용하여 적절하게 설치합니다.
- 이름, 주소 등은 더미 데이터이며 실제 데이터가 아닙니다.
import os
import pandas as pd
import numpy as np
from datetime import datetime, date
from dateutil.relativedelta import relativedelta
import math
import psycopg2
from sqlalchemy import create_engine
from sklearn import preprocessing
from sklearn.impute import SimpleImputer
from sklearn.model_selection import train_test_split
from sklearn.model_selection import TimeSeriesSplit
from imblearn.under_sampling import RandomUnderSampler
if 'PG_PORT' in os.environ:
pgconfig = {
'host': 'db',
'port': os.environ['PG_PORT'],
'database': os.environ['PG_DATABASE'],
'user': os.environ['PG_USER'],
'password': os.environ['PG_PASSWORD'],
}
# pd.read_sql용 커넥터
conn = psycopg2.connect(**pgconfig)
df_customer = pd.read_sql(sql='select * from customer', con=conn)
df_category = pd.read_sql(sql='select * from category', con=conn)
df_product = pd.read_sql(sql='select * from product', con=conn)
df_receipt = pd.read_sql(sql='select * from receipt', con=conn)
df_store = pd.read_sql(sql='select * from store', con=conn)
df_geocode = pd.read_sql(sql='select * from geocode', con=conn)
else:
if not os.path.exists('../data/'):
!git clone https://github.com/The-Japan-DataScientist-Society/100knocks-preprocess
os.chdir('100knocks-preprocess/docker/work/answer')
dtype = {
'customer_id': str,
'gender_cd': str,
'postal_cd': str,
'application_store_cd': str,
'status_cd': str,
'category_major_cd': str,
'category_medium_cd': str,
'category_small_cd': str,
'product_cd': str,
'store_cd': str,
'prefecture_cd': str,
'tel_no': str,
'postal_cd': str,
'street': str
}
df_customer = pd.read_csv("../data/customer.csv", dtype=dtype)
df_category = pd.read_csv("../data/category.csv", dtype=dtype)
df_product = pd.read_csv("../data/product.csv", dtype=dtype)
df_receipt = pd.read_csv("../data/receipt.csv", dtype=dtype)
df_store = pd.read_csv("../data/store.csv", dtype=dtype)
df_geocode = pd.read_csv("../data/geocode.csv", dtype=dtype)
연습문제
P-021: 영수증 내역 데이터(df_receipt)에 대해 건수를 세어라.
len(df_receipt)
104681
해설:
코드 len(df_receipt)은 DataFrame df_receipt의 길이를 반환한다.
아래에서는 각 구성 요소에 대해 설명한다.
lens(): : 파이썬의 내장 함수로, 리스트나 문자열과 같은 객체의 길이를 반환합니다.
df_receipt : df_receipt : pandas에서 DataFrame 객체를 나타내는 변수이며, df_receipt라는 이름은 임의의 유효한 변수명일 수 있다.
len()과 df_receipt의 조합으로, len() 함수의 인수로 DataFrame의 df_receipt를 전달하여 df_receipt의 행 수를 반환하도록 파이썬에 요청하고 있습니다.
요약하면, 이 코드는 단순히 DataFrame의 행 수를 반환하는 것에 불과하다.
P-022: 영수증 내역 데이터(df_receipt)의 고객 ID(customer_id)에 대해 고유 건수를 세어라.
len(df_receipt['customer_id'].unique())
8307
헤설:
len(df_receipt['customer_id'.unique())
len(df_receipt['customer_id'].unique())는 df_receipt DataFrame의 customer_id 열에 포함된 고유한 고객 ID의 개수를 반환하는 코드입니다.
아래에서는 각 구성 요소에 대해 설명합니다.
len() : 파이썬의 내장 함수로 목록이나 문자열 등의 객체의 길이를 반환합니다.
df_receipt : df_receipt : pandas에서 DataFrame 객체를 나타내는 변수이며, df_receipt라는 이름은 임의의 유효한 변수명일 수 있다.
['customer_id']: df_receipt에서 customer_id라는 레이블을 가진 컬럼을 선택하는 DataFrame 인덱싱 작업이다. 결과 객체는 pandas Series입니다.
.unique(): pandas의 Series 메서드로 Series 내의 고유한 값을 numpy 배열로 반환한다. 이 경우 고유한 고객 ID의 numpy 배열을 반환합니다.
len(), df_receipt['customer_id'].unique(),()를 조합하고 있는데, len() 함수의 인수로 고유한 고객 ID의 numpy 배열을 전달하여 고유한 고객 ID의 개수를 반환하도록 파이썬에 요구하고 있습니다.
요약하면, 이 코드는 DataFrame 내의 고유한 고객 ID의 수를 반환하고 있는 것이다.
P-023: 영수증 내역 데이터(df_receipt)에 대해 매장 코드(store_cd)별 판매 금액(amount)과 판매 수량(quantity)을 합산하라.
# 코드 예시 1
df_receipt.groupby('store_cd').agg({'amount':'sum',
'quantity':'sum'}).reset_index()
store_cd | amount | quantity | |
---|---|---|---|
0 | S12007 | 638761 | 2099 |
1 | S12013 | 787513 | 2425 |
2 | S12014 | 725167 | 2358 |
3 | S12029 | 794741 | 2555 |
4 | S12030 | 684402 | 2403 |
5 | S13001 | 811936 | 2347 |
6 | S13002 | 727821 | 2340 |
7 | S13003 | 764294 | 2197 |
8 | S13004 | 779373 | 2390 |
9 | S13005 | 629876 | 2004 |
10 | S13008 | 809288 | 2491 |
11 | S13009 | 808870 | 2486 |
12 | S13015 | 780873 | 2248 |
13 | S13016 | 793773 | 2432 |
14 | S13017 | 748221 | 2376 |
15 | S13018 | 790535 | 2562 |
16 | S13019 | 827833 | 2541 |
17 | S13020 | 796383 | 2383 |
18 | S13031 | 705968 | 2336 |
19 | S13032 | 790501 | 2491 |
20 | S13035 | 715869 | 2219 |
21 | S13037 | 693087 | 2344 |
22 | S13038 | 708884 | 2337 |
23 | S13039 | 611888 | 1981 |
24 | S13041 | 728266 | 2233 |
25 | S13043 | 587895 | 1881 |
26 | S13044 | 520764 | 1729 |
27 | S13051 | 107452 | 354 |
28 | S13052 | 100314 | 250 |
29 | S14006 | 712839 | 2284 |
30 | S14010 | 790361 | 2290 |
31 | S14011 | 805724 | 2434 |
32 | S14012 | 720600 | 2412 |
33 | S14021 | 699511 | 2231 |
34 | S14022 | 651328 | 2047 |
35 | S14023 | 727630 | 2258 |
36 | S14024 | 736323 | 2417 |
37 | S14025 | 755581 | 2394 |
38 | S14026 | 824537 | 2503 |
39 | S14027 | 714550 | 2303 |
40 | S14028 | 786145 | 2458 |
41 | S14033 | 725318 | 2282 |
42 | S14034 | 653681 | 2024 |
43 | S14036 | 203694 | 635 |
44 | S14040 | 701858 | 2233 |
45 | S14042 | 534689 | 1935 |
46 | S14045 | 458484 | 1398 |
47 | S14046 | 412646 | 1354 |
48 | S14047 | 338329 | 1041 |
49 | S14048 | 234276 | 769 |
50 | S14049 | 230808 | 788 |
51 | S14050 | 167090 | 580 |
해설:
df_receipt.groupby('store_cd').agg({'amount':'sum', 'quantity':'sum'}).reset_index()라는 코드는 df_receipt DataFrame의 행을 store_cd 열로 그룹화하여 각 그룹 내 해당 열에 두 개의 집계 함수(금액과 수량에 대한 sum() )를 걸고 있습니다. 마지막으로 결과 DataFrame의 인덱스를 재설정하고 있습니다.
다음은 각 구성 요소에 대한 설명이다.
df_receipt: df_receipt: pandas의 DataFrame 객체를 나타내는 변수이며, df_receipt라는 이름은 유효한 변수 이름이면 무엇이든 상관없다.
.groupby('store_cd'): pandas의 DataFrame 메서드이며, DataFrame의 행을 store_cd 컬럼의 값으로 그룹화한다. 각 그룹에 개별적으로 함수를 적용하는 데 사용할 수 있는 GroupBy 객체를 생성한다.
.agg({'amount':'sum', 'quantity':'sum'}): pandas의 GroupBy 객체의 메소드이며, GroupBy 객체의 각 그룹의 amount 열과 quantity 열에 sum() 집계 함수를 적용하고 있습니다. 결과는 각 그룹의 해당 열의 합계를 포함하는 amount와 quantity 두 개의 열을 가진 DataFrame이 됩니다.
.reset_index(): 이것은 pandas의 DataFrame 메소드로, 결과 DataFrame의 인덱스를 기본 인덱스로 재설정합니다.
요약하면, 이 코드는 특정 열의 값으로 DataFrame의 행을 그룹화하고, 각 그룹에 대해 다른 두 열의 합계를 계산하고, 각 그룹에 대해 이들 열의 합계와 기본 인덱스를 가진 DataFrame을 반환하고 있습니다.
# 코드 예시 2
df_receipt.groupby('store_cd')[['amount','quantity']].agg('sum').reset_index()
store_cd | amount | quantity | |
---|---|---|---|
0 | S12007 | 638761 | 2099 |
1 | S12013 | 787513 | 2425 |
2 | S12014 | 725167 | 2358 |
3 | S12029 | 794741 | 2555 |
4 | S12030 | 684402 | 2403 |
5 | S13001 | 811936 | 2347 |
6 | S13002 | 727821 | 2340 |
7 | S13003 | 764294 | 2197 |
8 | S13004 | 779373 | 2390 |
9 | S13005 | 629876 | 2004 |
10 | S13008 | 809288 | 2491 |
11 | S13009 | 808870 | 2486 |
12 | S13015 | 780873 | 2248 |
13 | S13016 | 793773 | 2432 |
14 | S13017 | 748221 | 2376 |
15 | S13018 | 790535 | 2562 |
16 | S13019 | 827833 | 2541 |
17 | S13020 | 796383 | 2383 |
18 | S13031 | 705968 | 2336 |
19 | S13032 | 790501 | 2491 |
20 | S13035 | 715869 | 2219 |
21 | S13037 | 693087 | 2344 |
22 | S13038 | 708884 | 2337 |
23 | S13039 | 611888 | 1981 |
24 | S13041 | 728266 | 2233 |
25 | S13043 | 587895 | 1881 |
26 | S13044 | 520764 | 1729 |
27 | S13051 | 107452 | 354 |
28 | S13052 | 100314 | 250 |
29 | S14006 | 712839 | 2284 |
30 | S14010 | 790361 | 2290 |
31 | S14011 | 805724 | 2434 |
32 | S14012 | 720600 | 2412 |
33 | S14021 | 699511 | 2231 |
34 | S14022 | 651328 | 2047 |
35 | S14023 | 727630 | 2258 |
36 | S14024 | 736323 | 2417 |
37 | S14025 | 755581 | 2394 |
38 | S14026 | 824537 | 2503 |
39 | S14027 | 714550 | 2303 |
40 | S14028 | 786145 | 2458 |
41 | S14033 | 725318 | 2282 |
42 | S14034 | 653681 | 2024 |
43 | S14036 | 203694 | 635 |
44 | S14040 | 701858 | 2233 |
45 | S14042 | 534689 | 1935 |
46 | S14045 | 458484 | 1398 |
47 | S14046 | 412646 | 1354 |
48 | S14047 | 338329 | 1041 |
49 | S14048 | 234276 | 769 |
50 | S14049 | 230808 | 788 |
51 | S14050 | 167090 | 580 |
해설:
이 코드에서는 df_receipt 데이터 프레임에 대해 store_cd 컬럼을 사용하여 groupby 연산을 수행하고 amount와 quantity 컬럼을 합산하여 집계한다.
결과 데이터 프레임은 store_cd 컬럼의 고유한 값마다 하나의 행과 amount와 quantity 두 개의 컬럼을 가지며, 두 컬럼 모두 동일한 store_cd 값을 가진 모든 행의 각 값의 합계를 포함한다.
그런 다음 .reset_index() 메서드가 결과 데이터 프레임에서 호출되어 store_cd 컬럼을 인덱스에서 일반 컬럼으로 변환한다.
P-024: 영수증 내역 데이터(df_receipt)에 대해 고객 ID(customer_id)별로 가장 최근 매출 날짜(sales_ymd)를 구하여 10건 표시하라.
df_receipt.groupby('customer_id').agg({'sales_ymd': 'max'}).reset_index().head(10)
customer_id | sales_ymd | |
---|---|---|
0 | CS001113000004 | 20190308 |
1 | CS001114000005 | 20190731 |
2 | CS001115000010 | 20190405 |
3 | CS001205000004 | 20190625 |
4 | CS001205000006 | 20190224 |
5 | CS001211000025 | 20190322 |
6 | CS001212000027 | 20170127 |
7 | CS001212000031 | 20180906 |
8 | CS001212000046 | 20170811 |
9 | CS001212000070 | 20191018 |
해설:
이 코드에서는 df_receipt라는 DataFrame에 대해 customer_id 컬럼을 기반으로 groupby 연산을 실행하고 있습니다. 그런 다음 각 그룹의 sales_ymd 컬럼의 값을 max 함수로 집계하여 각 고객의 최신 구매일을 구하고 있습니다.
집계 결과 customer_id와 sales_ymd 두 개의 컬럼을 가진 새로운 DataFrame이 생성됩니다. 그런 다음 reset_index 함수를 사용하여 결과 DataFrame의 인덱스를 기본값으로 재설정하고 head(10) 함수를 사용하여 결과 DataFrame의 처음 10개의 행을 표시합니다.
즉, 이 코드의 출력은 각 customer_id의 최대 구매일(sales_ymd)을 나타내는 DataFrame이며, 처음 10줄만 표시됩니다.
P-025: 영수증 내역 데이터(df_receipt)에 대해 고객 ID(customer_id)별로 가장 오래된 매출 날짜(sales_ymd)를 구하여 10건 표시하라.
# 024와 같은 방식으로도 작성할 수 있지만 굳이 다른 방식으로 작성하여 해답 예시를 소개합니다.
df_receipt.groupby('customer_id').sales_ymd.min().reset_index().head(10)
customer_id | sales_ymd | |
---|---|---|
0 | CS001113000004 | 20190308 |
1 | CS001114000005 | 20180503 |
2 | CS001115000010 | 20171228 |
3 | CS001205000004 | 20170914 |
4 | CS001205000006 | 20180207 |
5 | CS001211000025 | 20190322 |
6 | CS001212000027 | 20170127 |
7 | CS001212000031 | 20180906 |
8 | CS001212000046 | 20170811 |
9 | CS001212000070 | 20191018 |
해설:
df_receipt.groupby('customer_id').agg({'sales_ymd': 'max'}).reset_index().head(10)는 df_receipt DataFrame 의 행을 customer_id 열로 그룹화하여 각 그룹 의 sales_ymd 열에 max() 집약 함수를 적용하고 있습니다. 마지막으로 결과 DataFrame의 인덱스를 재설정하여 처음 10개의 행을 반환합니다.
다음은 각 컴포넌트에 대한 설명입니다.
df_receipt: df_receipt: pandas의 DataFrame 객체를 나타내는 변수이며, df_receipt라는 이름은 임의의 유효한 변수 이름일 수 있다.
.groupby('customer_id'): pandas의 DataFrame 메서드이며, DataFrame의 행을 customer_id 컬럼의 값으로 그룹화한다. 각 그룹에 개별적으로 함수를 적용하는 데 사용할 수 있는 GroupBy 객체를 생성합니다.
.agg({'sales_ymd': 'max'}): pandas의 GroupBy 객체의 메소드이며, GroupBy 객체의 각 그룹의 sales_ymd 컬럼에 max() 집계 함수를 적용하고 있습니다. 결과는 각 그룹의 sales_ymd 컬럼의 최대값을 포함하는 sales_ymd 컬럼을 하나 가진 DataFrame이 된다.
.reset_index() : pandas의 DataFrame 메소드이며, 결과 DataFrame의 인덱스를 기본 인덱스로 재설정한다.
.head(10) : pandas의 DataFrame 메서드이며, DataFrame의 첫 10개의 행을 반환한다.
요약하면, 이 코드는 DataFrame의 행을 특정 열의 값으로 그룹화하고, 각 그룹에 대해 다른 열의 최대값을 구하고, 최대값과 기본 인덱스가 있는 DataFrame을 반환하고, 해당 DataFrame의 처음 10개의 행을 반환하고 있습니다. 이 코드는 각 고객의 최근 구매 날짜를 파악하는 데 유용합니다.
P-026: 영수증 내역 데이터(df_receipt)에 대해 고객 ID(customer_id)별로 가장 최근 매출 날짜(sales_ymd)와 가장 오래된 매출 날짜(sales_ymd)를 구하고, 양자가 서로 다른 데이터 10건을 표시하라.
df_tmp = df_receipt.groupby('customer_id'). \
agg({'sales_ymd':['max','min']}).reset_index()
# 다중 인덱스(항목) 계층을 "_"로 연결하여 1계층 인덱스(항목)로 만들기
# df_tmp.columns = ['customer_id', 'sales_ymd_max', 'sales_ymd_min']으로 해도 된다.
df_tmp.columns = ["_".join(pair) for pair in df_tmp.columns]
df_tmp.query('sales_ymd_max != sales_ymd_min').head(10)
customer_id_ | sales_ymd_max | sales_ymd_min | |
---|---|---|---|
1 | CS001114000005 | 20190731 | 20180503 |
2 | CS001115000010 | 20190405 | 20171228 |
3 | CS001205000004 | 20190625 | 20170914 |
4 | CS001205000006 | 20190224 | 20180207 |
13 | CS001214000009 | 20190902 | 20170306 |
14 | CS001214000017 | 20191006 | 20180828 |
16 | CS001214000048 | 20190929 | 20171109 |
17 | CS001214000052 | 20190617 | 20180208 |
20 | CS001215000005 | 20181021 | 20170206 |
21 | CS001215000040 | 20171022 | 20170214 |
해설:
코드 df_tmp = df_receipt.groupby('customer_id').agg({'sales_ymd':['max','min']}).reset_index() df_tmp.query('sales_ymd_max ! = sales_ymd_min'). head(10)은 df_receipt DataFrame의 행을 customer_id 열로 그룹화하고, 각 그룹의 sales_ymd 열에 두 개의 집계 함수(max(), min())를 적용하여 각 고객의 구매 날짜의 최대값과 최소값을 포함한 DataFrame을 반환한다. 그리고 query() 메서드에서 최대 구매일과 최소 구매일이 다른 행만 선택하여 처음 10개의 행을 반환합니다.
다음은 각 컴포넌트에 대한 설명입니다.
df_receipt: df_receipt: pandas에서 DataFrame 객체를 나타내는 변수이며, df_receipt라는 이름은 임의의 유효한 변수 이름으로 지정할 수 있습니다.
.groupby('customer_id'): pandas의 DataFrame 메서드이며, DataFrame의 행을 customer_id 컬럼의 값으로 그룹화한다. 각 그룹에 개별적으로 함수를 적용하는 데 사용할 수 있는 GroupBy 객체를 생성합니다.
.agg({'sales_ymd':['max','min']}): pandas의 GroupBy 객체의 메소드로, GroupBy 객체의 각 그룹의 sales_ymd 컬럼에 두 개의 집계 함수(max()와 min())를 적용하고 있습니다. 결과는 각 그룹의 sales_ymd 컬럼의 최대값과 최소값을 각각 포함하는 sales_ymd_max와 sales_ymd_min이라는 두 개의 컬럼을 가진 DataFrame이 됩니다.
.reset_index() : 결과 DataFrame의 인덱스를 기본 인덱스로 재설정하는 pandas DataFrame 메소드입니다.
.query('sales_ymd_max ! = sales_ymd_min') : sales_ymd_max 열의 값이 sales_ymd_min 열의 값과 같지 않은 DataFrame의 행만 선택하는 pandas DataFrame 메서드이다. 이는 query() 메서드의 인수로 전달된 문자열의 부울 식을 사용하여 수행한다.
.head(10)이다. 이것은 pandas의 DataFrame 메서드이며, DataFrame의 처음 10개의 행을 반환합니다.
요약하면, 이 코드는 DataFrame의 행을 특정 열의 값으로 그룹화하고, 각 그룹에 대해 다른 열의 최대값과 최소값을 구하고, 최대값과 최소값, 그리고 기본 인덱스가 포함된 DataFrame을 반환한다. 그런 다음 최대값과 최소값이 다른 행만 선택하고 결과 DataFrame의 처음 10개의 행을 반환한다. 이 코드는 다른 날짜에 구매한 고객을 식별하는 데 유용하다.
P-027: 영수증 내역 데이터(df_receipt)에 대해 매장 코드(store_cd)별 매출 금액(amount)의 평균을 계산하여 내림차순으로 TOP5를 표시하라.
df_receipt.groupby('store_cd').agg({'amount':'mean'}).reset_index(). \
sort_values('amount', ascending=False).head(5)
store_cd | amount | |
---|---|---|
28 | S13052 | 402.867470 |
12 | S13015 | 351.111960 |
7 | S13003 | 350.915519 |
30 | S14010 | 348.791262 |
5 | S13001 | 348.470386 |
해설:
df_receipt.groupby('store_cd').agg({'amount':'mean'}).reset_index().sort_values('amount', ascending=False).head(5)는 df_receipt DataFrame의 행을 store_cd 컬럼으로 그룹화하고, 각 그룹에 대해 amount 컬럼의 평균값을 계산하여 평균값과 store_cd 컬럼으로 DataFrame을 반환하는 코드이다. 그런 다음, 얻어진 DataFrame의 인덱스를 재설정하고 금액의 평균값으로 내림차순으로 정렬한다. 마지막으로 결과 DataFrame의 처음 5줄을 반환한다.
다음은 각 컴포넌트에 대한 설명입니다.
df_receipt: df_receipt: pandas의 DataFrame 객체를 나타내는 변수이며, df_receipt라는 이름은 유효한 변수 이름이면 무엇이든 상관없다.
.groupby('store_cd'): pandas의 DataFrame 메서드이며, DataFrame의 행을 store_cd 컬럼의 값으로 그룹화한다. 각 그룹에 개별적으로 함수를 적용하는 데 사용할 수 있는 GroupBy 객체를 생성한다.
.agg({'amount':'mean'}): pandas의 GroupBy 객체의 메소드이며, GroupBy 객체의 각 그룹의 amount 열에 mean() 집계 함수를 적용하고 있습니다. 결과는 각 그룹의 금액 컬럼의 평균값을 포함하는 amount라는 하나의 컬럼을 가진 DataFrame이 됩니다.
.reset_index(): 결과 DataFrame의 인덱스를 기본 인덱스로 재설정하는 pandas의 DataFrame 메소드입니다.
.sort_values('amount', ascending=False): pandas의 DataFrame 메서드로 DataFrame의 행을 amount 열의 값으로 내림차순으로 정렬하며, ascending=False 파라미터는 내림차순으로 정렬할 것을 지정합니다. 을 지정합니다.
.head(5): pandas의 DataFrame 메서드이며, DataFrame의 처음 5줄을 반환합니다.
요약하면, 이 코드는 DataFrame의 행을 특정 열의 값으로 그룹화하고, 각 그룹에 대해 다른 열의 평균값을 구하고, 평균값과 그룹화된 열을 포함한 DataFrame을 반환합니다. 그리고 얻은 DataFrame의 인덱스를 재설정하고 평균값으로 내림차순으로 정렬하여 얻은 DataFrame의 처음 5개 행을 반환합니다. 이 코드는 평균 매출이 가장 높은 매장을 식별하는 데 유용합니다.
P-028: 영수증 내역 데이터(df_receipt)에 대해 매장 코드(store_cd)별 매출 금액(amount)의 중앙값을 계산하여 내림차순으로 TOP5를 표시하라.
df_receipt.groupby('store_cd').agg({'amount':'median'}).reset_index(). \
sort_values('amount', ascending=False).head(5)
store_cd | amount | |
---|---|---|
28 | S13052 | 190.0 |
30 | S14010 | 188.0 |
51 | S14050 | 185.0 |
44 | S14040 | 180.0 |
7 | S13003 | 180.0 |
해설:
df_receipt.groupby('store_cd').agg({'amount':'median'}).reset_index().sort_values('amount', ascending=False).head(5)는 df_receipt DataFrame의 행을 store_cd 컬럼으로 그룹화하고, 각 그룹에 대해 amount 컬럼의 중앙값을 계산하여 store_cd 컬럼과 중앙값으로 DataFrame을 반환하고 있다. 그런 다음 결과 DataFrame의 인덱스를 재설정하고 금액의 중앙값을 기준으로 내림차순으로 정렬합니다. 마지막으로 결과 DataFrame의 처음 5줄을 반환합니다.
다음은 각 컴포넌트에 대한 설명입니다.
df_receipt: df_receipt: pandas의 DataFrame 객체를 나타내는 변수이며, df_receipt라는 이름은 유효한 변수 이름이면 무엇이든 상관없다.
.groupby('store_cd'): pandas의 DataFrame 메서드이며, DataFrame의 행을 store_cd 컬럼의 값으로 그룹화한다. 각 그룹에 개별적으로 함수를 적용하는 데 사용할 수 있는 GroupBy 객체를 생성한다.
.agg({'amount':'median'}): pandas의 GroupBy 객체의 메소드이며, GroupBy 객체의 각 그룹의 amount 컬럼에 median() 집계 함수를 적용하고 있습니다. 결과는 각 그룹의 amount 컬럼의 중앙값을 포함하는 amount라는 하나의 컬럼을 가진 DataFrame이 된다.
.reset_index(): 이것은 pandas의 DataFrame 메소드로, 결과 DataFrame의 인덱스를 기본 인덱스로 재설정하고 있습니다.
.sort_values('amount', ascending=False): pandas의 DataFrame 메서드로 DataFrame의 행을 amount 열의 값으로 내림차순으로 정렬하는 DataFrame 메서드이며, ascending=False 파라미터는 내림차순으로 정렬할 것을 지정한다. 을 지정합니다.
.head(5): pandas의 DataFrame 메서드이며, DataFrame의 처음 5줄을 반환한다.
요약하면, 이 코드는 DataFrame의 행을 특정 열의 값으로 그룹화하고, 각 그룹에 대해 다른 열의 중앙값을 구하고, 중앙값과 그룹화된 열이 포함된 DataFrame을 반환하고 있습니다. 그리고 얻은 DataFrame의 인덱스를 재설정하고 중앙값으로 내림차순으로 정렬하여 얻은 DataFrame의 처음 5개 행을 반환합니다. 이 코드는 매출의 중앙값이 가장 높은 매장을 식별하는 데 유용합니다.
P-029: 영수증 내역 데이터(df_receipt)에 대해 매장 코드(store_cd)별로 상품 코드(product_cd)의 최빈값을 구하여 10건씩 표시하라.
df_receipt.groupby('store_cd').product_cd. \
apply(lambda x: x.mode()).reset_index().head(10)
store_cd | level_1 | product_cd | |
---|---|---|---|
0 | S12007 | 0 | P060303001 |
1 | S12013 | 0 | P060303001 |
2 | S12014 | 0 | P060303001 |
3 | S12029 | 0 | P060303001 |
4 | S12030 | 0 | P060303001 |
5 | S13001 | 0 | P060303001 |
6 | S13002 | 0 | P060303001 |
7 | S13003 | 0 | P071401001 |
8 | S13004 | 0 | P060303001 |
9 | S13005 | 0 | P040503001 |
헤설:
df_receipt.groupby('store_cd').product_cd.apply(lambda x: x.mode()).reset_index().head(10)는 df_receipt DataFrame의 행을 store_cd 열로 그룹화하여, 각 그룹에 대해 product_cd 열의 모드 값을 구하는 코드입니다. reset_index() 메서드는 결과 DataFrame의 인덱스를 기본 인덱스로 재설정하는 메서드이며, 해당 모드 값과 store_cd 열이 포함된 DataFrame을 반환한다.
다음은 각 컴포넌트에 대한 설명입니다.
df_receipt: df_receipt: pandas에서 DataFrame 객체를 나타내는 변수이며, df_receipt라는 이름은 임의의 유효한 변수 이름일 수 있다.
.groupby('store_cd'): pandas의 DataFrame 메서드이며, DataFrame의 행을 store_cd 컬럼의 값으로 그룹화한다. 각 그룹에 개별적으로 함수를 적용하는 데 사용할 수 있는 GroupBy 객체를 생성합니다.
.product_cd : DataFrame의 product_cd 컬럼에 접근하는 pandas DataFrame 속성입니다.
.apply(lambda x: x.mode()) : pandas GroupBy 객체의 각 그룹에 mode() 함수를 적용하는 pandas GroupBy 객체의 메소드이며, mode() 함수는 각 그룹에서 가장 빈번하게 발생하는 값을 반환한다. 결과 객체는 원래 그룹과 동일한 길이의 시리즈입니다.
.reset_index(): pandas의 DataFrame 메소드로, 결과 DataFrame의 인덱스를 기본 인덱스로 재설정합니다.
요약하면, 이 코드는 특정 열의 값으로 DataFrame의 행을 그룹화하고, 각 그룹에 대해 다른 열의 모드 값을 구하고, 모드 값과 그룹화 된 열을 포함하는 DataFrame을 반환하고 있습니다. 사용됩니다. 이 코드는 각 매장에서 판매되는 가장 인기 있는 상품을 파악하는 데 유용합니다.
P-030: 영수증 내역 데이터(df_receipt)에 대해 매장 코드(store_cd)별 매출 금액(amount)의 분산을 계산하여 내림차순으로 5개씩 표시하시오.
df_receipt.groupby('store_cd').amount.var(ddof=0).reset_index(). \
sort_values('amount', ascending=False).head(5)
store_cd | amount | |
---|---|---|
28 | S13052 | 440088.701311 |
31 | S14011 | 306314.558164 |
42 | S14034 | 296920.081011 |
5 | S13001 | 295431.993329 |
12 | S13015 | 295294.361116 |
해설:
df_receipt.groupby('store_cd').amount.var(ddof=0).reset_index().sort_values('amount', ascending=False).head(5)는 df_receipt DataFrame의 행을 store_cd 열로 그룹화하고, ddof=0으로 각 그룹에 대해 금액 열에 대한 분산을 계산하여 그 분산 값과 store_cd 열의 데이터 프레임을 반환하는 코드입니다. reset_index() 메서드는 결과 DataFrame의 인덱스를 기본 인덱스로 재설정합니다. 그리고 결과 DataFrame을 분산값의 내림차순으로 정렬하여 처음 5개 행을 반환한다.
다음은 각 구성 요소에 대한 설명입니다.
df_receipt: df_receipt: pandas의 DataFrame 객체를 나타내는 변수이며, df_receipt라는 이름은 임의의 유효한 변수 이름일 수 있다.
.groupby('store_cd'): pandas의 DataFrame 메소드이며, DataFrame의 행을 store_cd 컬럼의 값으로 그룹화한다. 이렇게 하면 각 그룹에 개별적으로 함수를 적용하는 데 사용할 수 있는 GroupBy 객체가 생성됩니다.
.amount.var(ddof=0): GroupBy 객체의 각 그룹에 대해 ddof=0으로 amount 열의 분산을 계산하는 pandas DataFrame 메소드이며, ddof 매개 변수는 표본 분산 계산에 사용할 제곱근인 자유도 델타를 지정합니다. ddof에 0을 지정하면 표본 분산이 아닌 모집단 분산을 계산해야 함을 나타낸다. 결과는 분산값과 store_cd 값을 인덱스로 하는 Series입니다.
.reset_index() : pandas의 DataFrame 메소드이며, 결과 DataFrame의 인덱스를 기본 인덱스로 재설정하는 메소드입니다.
.sort_values('amount', ascending=False) : pandas의 DataFrame 메서드로 DataFrame의 행을 amount 열의 값으로 내림차순으로 정렬하는 DataFrame 메서드이며, ascending=False 파라미터는 정렬 순서를 내림차순으로 할 것 을 지정합니다.
.head(5): pandas의 DataFrame 메서드이며, DataFrame의 처음 5줄을 반환합니다.
요약하면, 이 코드는 DataFrame의 행을 특정 열의 값으로 그룹화하고, 각 그룹에 대해 다른 열의 모분산을 구하고, 분산 값과 그룹화 된 열을 포함하는 DataFrame을 반환합니다. 그리고 얻은 DataFrame의 인덱스를 재설정하고 분산값의 내림차순으로 정렬하여 얻은 DataFrame의 처음 5개 행을 반환합니다. 이 코드는 매출 변동이 큰 매장을 식별하는 데 유용합니다.
P-031: 영수증 내역 데이터(df_receipt)에 대해 매장 코드(store_cd)별 매출 금액(amount)의 표준편차를 계산하여 내림차순으로 5건씩 표시하라.
TIPS:
Pandas와 Numpy에서 ddof의 기본값이 다르다는 점에 주목하자Pandas: DataFrame.std(self, axis=None, skipna=None, level=None, ddof=1, numeric_only=None, **kwargs) Numpy: numpy.std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=)
df_receipt.groupby('store_cd').amount.std(ddof=0).reset_index(). \
sort_values('amount', ascending=False).head(5)
store_cd | amount | |
---|---|---|
28 | S13052 | 663.391816 |
31 | S14011 | 553.456916 |
42 | S14034 | 544.903736 |
5 | S13001 | 543.536561 |
12 | S13015 | 543.409938 |
해설:
df_receipt.groupby('store_cd').amount.std(ddof=0).reset_index().sort_values('amount', ascending=False).head(5)는 df_receipt DataFrame 의 행을 store_cd 열로 그룹화하고, 각 그룹에 대해 ddof=0으로 amount 열의 표준 편차를 계산하여 표준 편차 값과 store_cd 열이 있는 데이터 프레임을 반환하는 코드입니다. 기본 인덱스로 재설정합니다. 그리고 얻은 DataFrame을 표준편차 값으로 내림차순으로 정렬하여 처음 5개 행을 반환합니다.
다음은 각 구성 요소에 대한 설명입니다.
df_receipt: df_receipt: pandas의 DataFrame 객체를 나타내는 변수이며, df_receipt라는 이름은 임의의 유효한 변수 이름일 수 있다.
.groupby('store_cd'): pandas의 DataFrame 메소드이며, DataFrame의 행을 store_cd 컬럼의 값으로 그룹화한다. 이렇게 하면 각 그룹에 개별적으로 함수를 적용하는 데 사용할 수 있는 GroupBy 객체가 생성됩니다.
.amount.std(ddof=0) : GroupBy 객체의 각 그룹의 amount 열의 표준편차를 ddof=0으로 계산하는 pandas DataFrame 메소드입니다. degrees of freedom)를 지정하는데, ddof에 0을 지정하면 표본 표준편차가 아닌 모집단의 표준편차를 계산하게 된다. 결과는 표준편차 값과 store_cd의 값을 인덱스로 하는 Series가 된다.
.reset_index() : pandas의 DataFrame 메소드이며, 결과 DataFrame의 인덱스를 기본 인덱스로 재설정한다.
.sort_values('amount', ascending=False) : pandas의 DataFrame 메서드로 DataFrame의 행을 amount 열의 값으로 내림차순으로 정렬하는 DataFrame 메서드이며, ascending=False 파라미터는 내림차순으로 정렬할 것 을 지정합니다.
.head(5): pandas의 DataFrame 메서드이며, DataFrame의 처음 5줄을 반환한다.
요약하면, 이 코드는 DataFrame의 행을 특정 열의 값으로 그룹화하고, 각 그룹에 대해 다른 열의 모표준편차를 구하고, 표준편차 값과 그룹화한 열이 포함된 DataFrame을 반환하고 있습니다. 그리고 얻은 DataFrame의 인덱스를 재설정하고 표준편차 값으로 내림차순으로 정렬하여 얻은 DataFrame의 처음 5개 행을 반환합니다. 이 코드는 매출 편차가 큰 매장을 식별하는 데 유용합니다.
P-032: 영수증 내역 데이터(df_receipt)의 매출 금액(amount)에 대해 25% 단위로 백분위수 값을 구하라.
# 코드 예시 1
np.percentile(df_receipt['amount'], q=np.arange(1, 5) * 25)
array([ 102., 170., 288., 10925.])
해설 :
np.percentile(df_receipt['amount'], q=np.range(1, 5) * 25)라는 코드는 NumPy 라이브러리의 np.percentile() 함수를 사용하여 df_receipt DataFrame의 amount 열의 값의 사분위수 수를 계산한다.
다음은 각 요소에 대해 설명한다.
np.percentile() : 배열의 백분율을 계산하는 NumPy 함수이다. 첫 번째 인수는 백분위수를 계산할 배열, 두 번째 인수는 계산할 백분위수 값. q 매개 변수는 계산할 백분위수를 지정하는 데 사용된다. 예를 들어, q=np.range(1, 5) * 25는 데이터 분포에서 25, 50, 75 위치의 백분위수를 계산한다. 이는 np.range(1, 5) * 25 식이 분포에서 백분위수 위치인 값 [25, 50, 75]의 배열을 생성하기 때문이다.
df_receipt['amount'] : df_receipt['amount']: df_receipt DataFrame의 amount 열을 나타내는 pandas Series 객체이며, df_receipt DataFrame은 현재 환경에 존재하는 것으로 가정한다. 로 가정한다.
q=np.range(1, 5) * 25: 계산할 백분위수를 지정하는 NumPy 배열이다. np.range(1, 5) * 25 식은 분포에서 백분위수의 위치인 값 [25, 50, 75]를 가진 배열을 생성한다.
이 코드는 df_receipt DataFrame의 amount 열의 사분위를 계산한다. 이는 분포를 4등분하는 값입니다. 첫 번째 사분위수(Q1)는 25번째 사분위수, 두 번째 사분위수(Q2)는 50번째 사분위수(중앙값이라고도 함), 세 번째 사분위수(Q3)는 75번째 사분위수이다. 이 코드의 출력은 사분위수 배열이며, 이를 통해 금액 항목의 분포를 요약할 수 있다.
# 코드 예시 2
df_receipt.amount.quantile(q=np.arange(1, 5) / 4)
0.25 102.0 0.50 170.0 0.75 288.0 1.00 10925.0 Name: amount, dtype: float64
해설 :
이 코드는 pandas의 quantile() 함수를 사용하여 df_receipt dataframe의 amount 열의 사분위를 계산하는 코드입니다. q 매개 변수는 1/4, 2/4(중간값), 3/4, 4/4(최대값) 중 계산할 사분위를 지정합니다.
이 코드에서는 df_receipt의 amount 열에 대해 quantile()을 호출하고 q 파라미터에 사분위수 1, 2, 3, 4에 각각 해당하는 값[0.25, 0.5, 0.75, 1.0]의 배열을 설정하여 사분위를 계산하고 있습니다.
이 코드의 결과 출력은 4개의 값의 배열이 되며, 각 값은 해당 사분위수 값을 나타냅니다.
P-033: 영수증 내역 데이터(df_receipt)에 대해 매장 코드(store_cd)별 매출 금액(amount)의 평균을 계산하여 330개 이상을 추출하라.
df_receipt.groupby('store_cd').amount.mean(). \
reset_index().query('amount >= 330')
store_cd | amount | |
---|---|---|
1 | S12013 | 330.194130 |
5 | S13001 | 348.470386 |
7 | S13003 | 350.915519 |
8 | S13004 | 330.943949 |
12 | S13015 | 351.111960 |
16 | S13019 | 330.208616 |
17 | S13020 | 337.879932 |
28 | S13052 | 402.867470 |
30 | S14010 | 348.791262 |
31 | S14011 | 335.718333 |
38 | S14026 | 332.340588 |
46 | S14045 | 330.082073 |
48 | S14047 | 330.077073 |
해설:
df_receipt.groupby('store_cd').amount.mean().reset_index().query('amount >= 330')는 df_receipt DataFrame을 store_cd 열로 그룹화하여 각 그룹의 amount 열의 평균값을 계산하고, 결과 DataFrame의 인덱스를 재설정하고, 결과 DataFrame을 amount의 평균값이 330 이상인 행만 포함하도록 필터링하는 코드입니다.
다음은 각 구성 요소에 대한 설명입니다.
df_receipt.groupby('store_cd'): df_receipt의 DataFrame을 store_cd 컬럼의 값으로 그룹화한다.
.amount.mean(): 각 그룹의 amount 컬럼의 평균값을 계산합니다.
.reset_index(): 결과 DataFrame의 인덱스를 재설정합니다.
.query('amount >= 330'): amount의 평균값이 330 이상인 행만 포함하도록 결과 DataFrame을 필터링합니다.
요약하면, 이 코드는 평균 거래 금액이 330 이상인 매장만 선택한다.
P-034: 영수증 내역 데이터(df_receipt)에 대해 고객 ID(customer_id)별로 매출 금액(amount)을 합산하여 전체 고객의 평균을 구하시오. 단, 고객 ID가 “Z”로 시작하는 것은 비회원을 의미하므로 제외하여 계산한다.
# 코드 예시 1: query를 사용하지 않는 방법
df_receipt[~df_receipt['customer_id'].str.startswith("Z")]. \
groupby('customer_id').amount.sum().mean()
2547.742234529256
해설:
df_receipt[~df_receipt['customer_id'].str.startswith("Z")].groupby('customer_id').amount.sum().mean()라는 코드에서는 다음과 같이 됩니다.
df_receipt[~df_receipt['customer_id'].str.startswith("Z")]: 이것은 df_receipt DataFrame을 필터링하여 customer_id 열이 "Z"로 시작하는 행을 제외합니다. 틸다(~) 문자는 str.startswith() 메서드가 반환하는 부울 값을 반전시키기 위한 부울 연산자로 사용됩니다.
.groupby('customer_id').amount.sum(): 필터링된 DataFrame을 customer_id 컬럼으로 그룹화하고 각 그룹의 amount 컬럼의 합계를 계산한다.
.mean(): 각 고객(customer_id가 "Z"로 시작하는 고객 제외)이 사용한 총 금액을 나타내는 결과 시리즈의 평균값을 계산한다.
요약하면, 이 코드는 df_receipt DataFrame의 customer_id가 "Z"로 시작하지 않는 각 고객이 사용한 금액의 평균을 계산한다. 이는 단골 고객의 구매 행동을 파악하는 데 도움이 될 것으로 보인다.
# 코드 예시 2: query를 사용하는 방법
df_receipt.query('not customer_id.str.startswith("Z")',
engine='python').groupby('customer_id').amount.sum().mean()
2547.742234529256
해설:
이 코드는 익명이 아닌 고객의 평균 소비액을 계산한다. 아래는 그 구조입니다.
df_receipt는 트랜잭션에 대한 정보를 담고 있는 DataFrame이다.
query 메서드를 사용하여 customer_id가 "Z"로 시작하는 트랜잭션을 필터링하고 있다. 이는 str.startswith() 메서드를 사용하여 문자열이 특정 문자 또는 부분 문자열로 시작하는지 여부를 검사하는 str.startswith() 메서드를 사용하여 수행됩니다.
완성된 DataFrame은 groupby 메서드를 사용하여 customer_id로 그룹화됩니다.
금액 열은 sum 메서드로 선택되어 각 고객이 사용한 금액의 합계가 계산됩니다.
그런 다음 mean 메서드를 사용하여 이전 단계에서 계산된 금액의 평균을 계산합니다. 이것이 이 코드의 최종 결과입니다.
P-035: 영수증 내역 데이터(df_receipt)에 대해 고객 ID(customer_id)별로 매출 금액(amount)을 합산하여 전체 고객의 평균을 구하고, 평균 이상 쇼핑을 한 고객을 추출하여 10건씩 표시하시오. 단, 고객 ID가 “Z”로 시작하는 것은 비회원을 의미하므로 제외하여 계산한다.
df_amount_sum = df_receipt[~df_receipt['customer_id'].str.startswith("Z")].\
groupby('customer_id').amount.sum()
amount_mean = df_amount_sum.mean()
df_amount_sum = df_amount_sum.reset_index()
df_amount_sum[df_amount_sum['amount'] >= amount_mean].head(10)
customer_id | amount | |
---|---|---|
2 | CS001115000010 | 3044 |
4 | CS001205000006 | 3337 |
13 | CS001214000009 | 4685 |
14 | CS001214000017 | 4132 |
17 | CS001214000052 | 5639 |
21 | CS001215000040 | 3496 |
30 | CS001304000006 | 3726 |
32 | CS001305000005 | 3485 |
33 | CS001305000011 | 4370 |
53 | CS001315000180 | 3300 |
해설 :
코드 df_amount_sum = df_receipt[~df_receipt['customer_id'].str.startswith("Z")].groupby('customer_id').amount.sum(), amount_mean = df_amount. amount_sum. mean(), df_amount_sum = df_amount_sum.reset_index(), df_amount_sum[df_amount_sum['amount'] >= amount_mean].head(10) 은 다음과 같이 있습니다.
df_receipt[~df_receipt['customer_id'].str.startswith("Z")].groupby('customer_id').amount.sum(): df_receipt의 DataFrame에서 customer_id 컬럼이 "Z"로 시작하는 행을 제외하고 customer_id 컬럼으로 그룹화하여 각 그룹의 amount 컬럼의 합계를 계산한다. 결과 객체는 각 고객(customer_id가 "Z"로 시작하는 고객 제외)이 사용한 금액의 합계를 나타내는 Series이다.
amount_mean = df_amount_sum.mean(): df_receipt DataFrame의 customer_id가 "Z"로 시작하지 않는 고객의 평균 지출 금액을 나타내는 df_amount_sum Series의 평균값을 계산한다.
df_amount_sum = df_amount_sum.reset_index(): df_amount_sum 시리즈의 인덱스를 재설정하여 customer_id와 amount 두 개의 컬럼을 가진 DataFrame으로 변환한다.
df_amount_sum[df_amount_sum['amount'] >= amount_mean].head(10): df_amount_sum의 DataFrame을 필터링하여 amount 칼럼이 amount_mean 이상의 행만 포함하도록 하고, 결과 DataFrame의 처음 10개의 행을 반환한다.
요약하면, 이 코드는 df_receipt DataFrame의 customer_id가 "Z"로 시작하지 않는 모든 고객의 평균 지출액 이상의 지출액을 가진 고객을 선택한다. 결과 DataFrame에는 선택된 각 고객의 customer_id와 총 지출 금액이 총 지출 금액의 내림차순으로 정렬되어 저장된다.
P-036: 영수증 내역 데이터(df_receipt)와 매장 데이터(df_store)를 내부적으로 결합하여 영수증 내역 데이터의 모든 항목과 매장 데이터의 매장명(store_name)을 10건씩 표시하라.
pd.merge(df_receipt, df_store[['store_cd','store_name']],
how='inner', on='store_cd').head(10)
sales_ymd | sales_epoch | store_cd | receipt_no | receipt_sub_no | customer_id | product_cd | quantity | amount | store_name | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 20181103 | 1541203200 | S14006 | 112 | 1 | CS006214000001 | P070305012 | 1 | 158 | 葛が谷店 |
1 | 20181116 | 1542326400 | S14006 | 112 | 2 | ZZ000000000000 | P080401001 | 1 | 48 | 葛が谷店 |
2 | 20170118 | 1484697600 | S14006 | 1162 | 1 | CS006815000006 | P050406035 | 1 | 220 | 葛が谷店 |
3 | 20190524 | 1558656000 | S14006 | 1192 | 1 | CS006514000034 | P060104003 | 1 | 80 | 葛が谷店 |
4 | 20190419 | 1555632000 | S14006 | 112 | 2 | ZZ000000000000 | P060501002 | 1 | 148 | 葛が谷店 |
5 | 20181119 | 1542585600 | S14006 | 1152 | 2 | ZZ000000000000 | P050701001 | 1 | 88 | 葛が谷店 |
6 | 20171211 | 1512950400 | S14006 | 1132 | 2 | CS006515000175 | P090903001 | 1 | 80 | 葛が谷店 |
7 | 20191021 | 1571616000 | S14006 | 1112 | 2 | CS006415000221 | P040602001 | 1 | 405 | 葛が谷店 |
8 | 20170710 | 1499644800 | S14006 | 1132 | 2 | CS006411000036 | P090301051 | 1 | 330 | 葛が谷店 |
9 | 20190805 | 1564963200 | S14006 | 112 | 1 | CS006211000012 | P050104001 | 1 | 115 | 葛が谷店 |
해설:
pd.merge(df_receipt, df_store[['store_cd','store_name']], how='inner', on='store_cd').head(10)라는 코드에서는 다음과 같이 처리한다.
df_store[['store_cd','store_name']] : df_store DataFrame 중 store_cd와 store_name이라는 두 개의 컬럼을 가진 하위 집합을 선택한다.
pd.merge(df_receipt, df_store[['store_cd','store_name']], how='inner', on='store_cd'): df_receipt DataFrame과 df_store['store_cd','store_name'] 사이의 내부 DataFrame을 병합한다. name'] 사이의 내부 결합을 수행하여 store_cd 컬럼의 DataFrame을 생성한다. store_cd 컬럼의 두 DataFrame을 병합하여 두 DataFrame에서 일치하는 값을 가진 행만 포함한다.
.head(10): 병합된 DataFrame의 처음 10개의 행을 반환한다.
요약하면, 이 코드는 df_receipt DataFrame과 df_store DataFrame을 store_cd 열로 병합하고 df_store DataFrame의 store_name 열을 병합된 DataFrame에 추가하고 있다. 결과 DataFrame에는 df_receipt의 트랜잭션이 발생한 매장에 대한 정보(store_cd, store_name, 기타 df_receipt DataFrame의 모든 열이 포함됨)가 포함된다.
P-037: 상품 데이터(df_product)와 카테고리 데이터(df_category)를 내부적으로 결합하여 상품 데이터의 전체 항목과 카테고리 데이터의 카테고리 소분류 이름(category_small_name) 10개를 표시하라.
pd.merge(df_product
, df_category[['category_small_cd','category_small_name']]
, how='inner', on='category_small_cd').head(10)
product_cd | category_major_cd | category_medium_cd | category_small_cd | unit_price | unit_cost | category_small_name | |
---|---|---|---|---|---|---|---|
0 | P040101001 | 04 | 0401 | 040101 | 198.0 | 149.0 | 弁当類 |
1 | P040101002 | 04 | 0401 | 040101 | 218.0 | 164.0 | 弁当類 |
2 | P040101003 | 04 | 0401 | 040101 | 230.0 | 173.0 | 弁当類 |
3 | P040101004 | 04 | 0401 | 040101 | 248.0 | 186.0 | 弁当類 |
4 | P040101005 | 04 | 0401 | 040101 | 268.0 | 201.0 | 弁当類 |
5 | P040101006 | 04 | 0401 | 040101 | 298.0 | 224.0 | 弁当類 |
6 | P040101007 | 04 | 0401 | 040101 | 338.0 | 254.0 | 弁当類 |
7 | P040101008 | 04 | 0401 | 040101 | 420.0 | 315.0 | 弁当類 |
8 | P040101009 | 04 | 0401 | 040101 | 498.0 | 374.0 | 弁当類 |
9 | P040101010 | 04 | 0401 | 040101 | 580.0 | 435.0 | 弁当類 |
해설:
코드 pd.merge(df_product , df_category[['category_small_cd','category_small_name']] 입니다. , how='inner', on='category_small_cd').head(10)에서는 다음과 같이 됩니다.
df_category[['category_small_cd','category_small_name']]: 이것은 df_category DataFrame 중 category_small_cd와 category_small_name이라는 두 개의 컬럼을 가진 하위 집합을 선택하는 것이다.
pd.merge(df_product , df_category[['category_small_cd','category_small_name']]) , how='inner', on='category_small_cd'): df_product DataFrame과 df_category[['category_small_cd','category_small_name']] 간의 내부 결합을 수행한다. category_small_cd 컬럼의 DataFrame을 생성한다. category_small_cd 컬럼의 두 DataFrame을 병합하여 두 DataFrame에서 일치하는 값을 가진 행만 포함한다.
.head(10): 병합된 DataFrame의 처음 10개의 행을 반환한다.
요약하면, 이 코드는 df_product DataFrame과 df_category DataFrame을 category_small_cd 열로 병합하고, df_category DataFrame에서 category_small_name 열을 병합한 DataFrame에 추가하고 있다. 결과 DataFrame은 df_product의 상품에 대한 정보를 포함하며, category_small_cd, category_small_name 및 df_product DataFrame의 다른 모든 컬럼을 포함한다.
P-038: 고객 데이터(df_customer)와 영수증 내역 데이터(df_receipt)에서 고객별 매출 금액의 총합을 구하여 10건을 표시하시오. 단, 판매 실적이 없는 고객에 대해서는 판매금액을 0으로 표시한다. 또한, 고객은 성별 코드(gender_cd)가 여성(1)인 고객을 대상으로 하며, 비회원(고객 ID가 “Z”로 시작하는 고객)은 제외한다.
df_amount_sum = df_receipt.groupby('customer_id').amount.sum().reset_index()
df_tmp = df_customer. \
query('gender_cd == "1" and not customer_id.str.startswith("Z")',
engine='python')
pd.merge(df_tmp['customer_id'], df_amount_sum,
how='left', on='customer_id').fillna(0).head(10)
customer_id | amount | |
---|---|---|
0 | CS021313000114 | 0.0 |
1 | CS031415000172 | 5088.0 |
2 | CS028811000001 | 0.0 |
3 | CS001215000145 | 875.0 |
4 | CS015414000103 | 3122.0 |
5 | CS033513000180 | 868.0 |
6 | CS035614000014 | 0.0 |
7 | CS011215000048 | 3444.0 |
8 | CS009413000079 | 0.0 |
9 | CS040412000191 | 210.0 |
해설:
코드 df_amount_sum = df_receipt.groupby('customer_id').amount.sum().reset_index() df_tmp = df_customer.query('gender_cd == "1" and not customer_id. str.startswith("Z")', engine='python') pd.merge(df_tmp['customer_id'], df_amount_sum, how='left', on='customer_id').fillna( 0).head(10)에서는 다음과 같이 되어 있습니다.
df_amount_sum = df_receipt.groupby('customer_id').amount.sum().reset_index(): 이것은 df_receipt DataFrame을 customer_id로 그룹화하여 각 고객의 amount 열을 합계하여 새로운 DataFrame df_amount_sum을 생성한다. 생성된 DataFrame은 customer_id와 amount 두 개의 컬럼을 가진다.
df_customer.query('gender_cd == "1" and not customer_id.str.startswith("Z")', engine='python'): 이것은 df_customer DataFrame 중 gender_cd가 1이고 이고 customer_id가 "Z"로 시작하지 않는 하위 집합을 선택합니다. engine='python' 인수는 startswith와 같은 문자열 메서드를 사용할 수 있도록 하기 위해 사용되었습니다.
pd.merge(df_tmp['customer_id'], df_amount_sum, how='left', on='customer_id'): df_tmp DataFrame의 customer_id 컬럼과 df_amount_sum을 병합한다. DataFrame의 customer_id 컬럼을 왼쪽 결합으로 결합한다. df_tmp DataFrame의 모든 행을 포함하고 df_amount_sum DataFrame의 금액 컬럼을 추가합니다(사용 가능한 경우).
.fillna(0): amount 컬럼의 누락된 값을 0으로 만듭니다.
.head(10): 병합된 DataFrame의 처음 10개의 행을 반환합니다.
요약하면, 이 코드는 df_receipt DataFrame의 각 고객이 사용한 총 금액을 계산한 후, df_customer DataFrame에서 남성이고 유효한 customer_id 값을 가진 고객의 하위 집합을 선택한다. 그런 다음 이 코드는 왼쪽 결합을 사용하여 customer_id 열로 두 DataFrame을 결합하고 결과 DataFrame에 각 고객이 사용한 금액의 합계를 포함한다. 결과 DataFrame에는 선택된 남성 고객의 customer_id 열과 amount 열이 포함된다.
P-039: 영수증 내역 데이터(df_receipt)에서 매출 일수가 많은 고객 상위 20건을 추출한 데이터와 매출 금액 합계가 많은 고객 상위 20건을 추출한 데이터를 각각 생성하고, 이 두 가지를 완전히 외부 결합하라. 단, 비회원(고객 ID가 “Z”로 시작하는 고객)은 제외한다.
df_data = df_receipt \
.query('not customer_id.str.startswith("Z")', engine='python')
df_cnt = df_data[~df_data.duplicated(subset=['customer_id', 'sales_ymd'])] \
.groupby('customer_id').sales_ymd.count().reset_index() \
.sort_values('sales_ymd', ascending=False).head(20)
df_sum = df_data.groupby('customer_id').amount.sum().reset_index() \
.sort_values('amount', ascending=False).head(20)
pd.merge(df_cnt, df_sum, how='outer', on='customer_id')
customer_id | sales_ymd | amount | |
---|---|---|---|
0 | CS040214000008 | 23.0 | NaN |
1 | CS015415000185 | 22.0 | 20153.0 |
2 | CS010214000010 | 22.0 | 18585.0 |
3 | CS010214000002 | 21.0 | NaN |
4 | CS028415000007 | 21.0 | 19127.0 |
5 | CS017415000097 | 20.0 | 23086.0 |
6 | CS016415000141 | 20.0 | 18372.0 |
7 | CS031414000051 | 19.0 | 19202.0 |
8 | CS014214000023 | 19.0 | NaN |
9 | CS022515000226 | 19.0 | NaN |
10 | CS021515000172 | 19.0 | NaN |
11 | CS039414000052 | 19.0 | NaN |
12 | CS021514000045 | 19.0 | NaN |
13 | CS022515000028 | 18.0 | NaN |
14 | CS030214000008 | 18.0 | NaN |
15 | CS021515000056 | 18.0 | NaN |
16 | CS014415000077 | 18.0 | NaN |
17 | CS021515000211 | 18.0 | NaN |
18 | CS032415000209 | 18.0 | NaN |
19 | CS031414000073 | 18.0 | NaN |
20 | CS001605000009 | NaN | 18925.0 |
21 | CS006515000023 | NaN | 18372.0 |
22 | CS011414000106 | NaN | 18338.0 |
23 | CS038415000104 | NaN | 17847.0 |
24 | CS035414000024 | NaN | 17615.0 |
25 | CS021515000089 | NaN | 17580.0 |
26 | CS032414000072 | NaN | 16563.0 |
27 | CS016415000101 | NaN | 16348.0 |
28 | CS011415000006 | NaN | 16094.0 |
29 | CS034415000047 | NaN | 16083.0 |
30 | CS007514000094 | NaN | 15735.0 |
31 | CS009414000059 | NaN | 15492.0 |
32 | CS030415000034 | NaN | 15468.0 |
33 | CS015515000034 | NaN | 15300.0 |
해설:
이 코드는 다음과 같은 단계를 수행합니다.
.query() 메서드를 사용하여 df_receipt 데이터 프레임에서 customer_id 열이 "Z"로 시작하지 않는 행을 필터링하여 df_data에 저장합니다.
df_data에서 customer_id 열과 sales_ymd 열을 기준으로 중복된 행을 제거하고 customer_id로 그룹화하여 판매일 수를 계산하여 df_cnt에 저장합니다.
df_cnt를 sales_ymd 열로 내림차순으로 정렬하여 상위 20개 행을 가져온다.
df_data를 customer_id로 그룹화하고, amount 컬럼을 합산하고, amount 컬럼에서 내림차순으로 정렬하여 상위 20개 행을 가져와 df_sum에 저장한다.
df_cnt와 df_sum 데이터 프레임을 how='outer' 매개변수를 가진 pd.merge() 메서드를 사용하여 customer_id 열로 병합하여 df_data에 저장한다(즉, 두 데이터 프레임의 모든 레코드를 병합 후의 데이터 프레임에 포함). 결과 데이터 프레임에는 판매일 수와 구매 금액의 합계를 기준으로 상위 20명의 고객이 포함된다.
P-040: 모든 매장과 모든 상품을 조합한 데이터를 생성하고 싶다. 매장 데이터(df_store)와 상품 데이터(df_product)를 직적분하여 건수를 계산하라.
df_store_tmp = df_store.copy()
df_product_tmp = df_product.copy()
df_store_tmp['key'] = 0
df_product_tmp['key'] = 0
len(pd.merge(df_store_tmp, df_product_tmp, how='outer', on='key'))
531590
해설:
이 코드는 외부 결합을 사용하여 두 개의 데이터 프레임 df_store와 df_product를 결합한다.
먼저 두 개의 임시 데이터 프레임 df_store_tmp와 df_product_tmp가 각각 df_store와 df_product의 복사본으로 생성됩니다. 이는 외부 바인딩이 병합하기 위해 공통 컬럼이 필요하기 때문이다.
마지막으로 pd.merge() 함수를 사용하여 두 데이터 프레임을 병합합니다. how='outer' 인수는 외부 병합을 원한다는 것을 나타내고 on='key'는 병합할 공통 컬럼을 지정합니다. 결과 데이터 프레임에는 두 데이터 프레임의 모든 행이 포함되며, 다른 데이터 프레임에 해당하는 데이터가 없는 셀에는 누락된 값(NaN)이 포함된다.
마지막으로 len()을 사용하여 병합된 데이터 프레임의 행 수를 가져온다. 두 데이터 프레임의 행 수는 동일하므로 내부 병합, 왼쪽 병합, 오른쪽 병합, 외부 병합 중 어느 것을 사용하든 출력은 동일하다. 이 경우 병합된 데이터 프레임의 총 행 수가 출력된다.
Comment