데이터 사이언스 100번의 노크(구조화 데이터 처리편)- Python Part 5 (Q81 to Q100)의 해설입니다.
처음에
- 먼저 다음 셀을 실행합니다.
- 필요한 라이브러리를 가져오고 데이터베이스에서 데이터를 읽습니다(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-081: 단가(unit_price)와 원가(unit_cost)의 결손값에 대해 각각의 평균값으로 보완한 새로운 상품 데이터를 작성하시오. 단, 평균값은 1원 미만은 반올림한다(반올림 또는 짝수로 반올림해도 무방하다). 보완 실시 후 각 항목에 대해 결손이 발생하지 않았는지도 확인해야 한다.
# 코드 예시 1 (Pandas의 fillna)
df_product_2 = df_product.fillna({
'unit_price':np.round(np.nanmean(df_product['unit_price'])),
'unit_cost':np.round(np.nanmean(df_product['unit_cost']))})
df_product_2.isnull().sum()
product_cd 0 category_major_cd 0 category_medium_cd 0 category_small_cd 0 unit_price 0 unit_cost 0 dtype: int64
해설:
이 코드는 df_product라는 pandas DataFrame에 대해 두 가지 처리를 수행합니다.
fillna() 메서드를 사용하여 unit_price와 unit_cost 열의 누락된 값을 각 열의 반올림된 평균값으로 채운다. 반올림된 평균값은 NumPy 라이브러리의 np.round() 및 np.nanmean() 함수를 사용하여 계산되며, fillna() 메서드는 사전을 인수로 받고, 키는 열 이름, 값은 누락된 값을 채우기 위한 값이다.
그리고 isnull() 메서드로 DataFrame에 누락된 값이 남아 있는지 확인하고, sum() 메서드로 각 열의 누락된 값의 개수를 합산한다. 그 결과 업데이트된 DataFrame df_product_2의 각 열의 결손값 수를 출력한다.
업데이트된 DataFrame df_product_2는 unit_price와 unit_cost 열의 결손값이 각각 반올림된 평균값으로 대체되었으며, 두 번째 줄의 출력은 fillna 작업 후 DataFrame에 얼마나 많은 결손값이 남았는지 보여준다.
# 코드 예시 2 (scikit-learn의 SimpleImputer)
imp_mean = SimpleImputer(missing_values=np.nan, strategy='mean')
imp_values = imp_mean.fit_transform(df_product[['unit_price', 'unit_cost']])
df_product_2 = df_product.copy()
df_product_2[['unit_price', 'unit_cost']] = imp_values.round()
df_product_2.isnull().sum()
product_cd 0 category_major_cd 0 category_medium_cd 0 category_small_cd 0 unit_price 0 unit_cost 0 dtype: int64
해설:
이 코드는 다음과 같은 작업을 수행합니다.
sklearn.impute 모듈에서 SimpleImputer 클래스를 가져오는데, SimpleImputer 클래스는 데이터 세트의 결손값을 입력하는 데 사용됩니다.
imp_mean이라는 SimpleImputer 인스턴스를 생성합니다. 이 컴퓨터는 결손값(이 경우 np.nan으로 표현됨)을 해당 열의 평균값으로 대체하게 된다. 인풋테이션의 전략은 'mean'로 설정되어 있다.
fit_transform() 메서드를 사용하여 df_product DataFrame의 unit_price 열과 unit_cost 열에 SimpleImputer 객체를 적용하여 결손값이 입력된 변환 후 DataFrame을 반환합니다.
copy() 메서드를 사용하여 df_product_2라는 원본 df_product DataFrame의 복사본을 생성한다.
df_product_2의 unit_price와 unit_cost 열을 imp_values.round()를 통해 입력한 값으로 대체한다. round() 메서드는 입력된 값을 가장 가까운 정수로 반올림하는 데 사용된다.
isnull() 메서드로 DataFrame에 누락된 값이 남아 있는지 확인하고, sum() 메서드로 각 열의 누락된 값의 개수를 집계한다. 그 결과 업데이트된 DataFrame df_product_2의 각 열의 결손값 수를 출력한다.
이 코드의 최종 출력은 각 열의 평균값으로 결손값을 임베드한 후 업데이트된 df_product_2 DataFrame의 결손값 수를 보여줍니다. 이 방법은 특히 결손값 수가 적은 경우 데이터 집합의 결손 데이터를 처리하는 데 유용하다.
P-082: 단가(unit_price)와 원가(unit_cost)의 결손값에 대해 각각의 중앙값으로 보완한 새로운 상품 데이터를 작성하시오. 단, 중앙값은 1원 미만은 반올림한다(반올림 또는 짝수로 반올림해도 무방하다). 보완 실시 후 각 항목에 대해 결손이 발생하지 않았는지도 확인해야 한다.
# 코드 예시 1 (Pandas의 fillna)
df_product_3 = df_product.fillna({
'unit_price':np.round(np.nanmedian(df_product['unit_price'])),
'unit_cost':np.round(np.nanmedian(df_product['unit_cost']))})
df_product_3.isnull().sum()
product_cd 0 category_major_cd 0 category_medium_cd 0 category_small_cd 0 unit_price 0 unit_cost 0 dtype: int64
해설:
이 코드에서는 먼저 "df_product"라는 DataFrame의 "unit_price"와 "unit_cost"라는 두 열의 누락된 값을 채우고 있습니다. 이 코드에서는 다음과 같은 인수를 가진 fillna 메서드를 사용하여 결손값을 채우고 있습니다.
첫 번째 인수는 "unit_price"와 "unit_cost"라는 두 개의 키를 가진 딕셔너리이며, 각각 해당 값에 매핑되어 있습니다. 이 값들은 DataFrame의 각 열에 적용되는 NumPy 라이브러리의 nanmedian 함수를 사용하여 계산되며, nanmedian은 NaN으로 표현되는 결손값을 무시하고 열의 중앙값을 계산한다.
이 코드에서 두 번째 인수는 생략되어 DataFrame의 다른 열의 결손값은 그대로 남게 된다.
이 작업의 결과는 "df_product_3"이라는 새로운 DataFrame이 된다.
다음 코드에서는 isnull() 메서드와 sum() 메서드를 호출하여 "df_product_3"의 DataFrame에 여전히 결손된 값이 있는지 확인합니다. 이 메서드는 DataFrame의 각 열에 누락된 값의 개수를 포함하는 Series 객체를 반환한다. 두 열에 모두 결손값이 없다고 출력되면 fillna의 조작이 성공했음을 확인할 수 있습니다.
# 코드 예시 2 (scikit-learn의 SimpleImputer)
imp_mean = SimpleImputer(missing_values=np.nan, strategy='median')
imp_values = imp_mean.fit_transform(df_product[['unit_price', 'unit_cost']])
df_product_3 = df_product.copy()
df_product_3[['unit_price', 'unit_cost']] = imp_values.round()
df_product_3.isnull().sum()
product_cd 0 category_major_cd 0 category_medium_cd 0 category_small_cd 0 unit_price 0 unit_cost 0 dtype: int64
해설:
이 코드는 scikit-learn의 SimpleImputer를 사용하여 DataFrame "df_product"의 "unit_price"와 "unit_cost" 열의 결손값에 대한 인풋을 수행한다.
코드의 첫 번째 줄은 "imp_mean"이라는 이름의 SimpleImputer 인스턴스를 초기화하고 있다. 이 클래스는 주어진 전략으로 결손값을 입력하는 방법을 제공하며, 이 경우 결손되지 않은 값의 중간값이며, missing_values 인수는 결손으로 간주할 값을 지정하며, 이 경우 NaN이 된다.
코드의 두 번째 줄은 "df_product" DataFrame의 "unit_price"와 "unit_cost" 열의 결손값을 입력하기 위해 "imp_mean" 객체의 fit_transform 메서드를 사용합니다. 이 메서드는 입력된 값을 포함하는 "imp_values"라는 이름의 NumPy 배열을 반환합니다.
코드의 세 번째 줄은 "df_product" DataFrame의 사본을 "df_product_3"이라는 이름으로 생성하고 있다. 이는 원본 DataFrame을 변경하지 않기 위함입니다.
코드의 네 번째 줄은 "df_product_3" DataFrame의 "unit_price"와 "unit_cost" 컬럼에 imp_values 배열에 대한 round() 메서드가 호출되어 가장 가까운 정수로 값을 반올림하고 있습니다.
코드의 마지막 줄은 isnull() 메서드와 sum() 메서드를 호출하여 'df_product_3' DataFrame에 여전히 누락된 값이 있는지 확인한다. 출력에 두 열 모두 누락된 값이 없는 것으로 나타나면, 인풋 연산이 성공했음을 확인할 수 있다.
P-083: 단가(unit_price)와 원가(unit_cost)의 결손값에 대해 각 상품의 카테고리 소분류 코드(category_small_cd)별로 산출한 중간값으로 보완한 새로운 상품 데이터를 작성한다. 단, 중앙값은 1원 미만은 반올림한다(반올림 또는 짝수로 반올림해도 무방하다). 보완 실시 후 각 항목에 대해 결손이 발생하지 않았는지도 확인해야 한다.
# 코드 예시 1
df_tmp = (df_product.groupby('category_small_cd')
.agg(median_price=('unit_price', 'median'),
median_cost=('unit_cost', 'median')).reset_index())
df_product_4 = pd.merge(df_product, df_tmp, how='inner', on='category_small_cd')
df_product_4['unit_price'] = df_product_4[['unit_price', 'median_price']]. \
apply(lambda x: np.round(x[1]) if np.isnan(x[0]) else x[0], axis=1)
df_product_4['unit_cost'] = df_product_4[['unit_cost', 'median_cost']]. \
apply(lambda x: np.round(x[1]) if np.isnan(x[0]) else x[0], axis=1)
df_product_4.isnull().sum()
product_cd 0 category_major_cd 0 category_medium_cd 0 category_small_cd 0 unit_price 0 unit_cost 0 median_price 0 median_cost 0 dtype: int64
해설:
이 코드는 DataFrame "df_product"의 "unit_price"와 "unit_cost" 열의 결손된 값을 각 카테고리의 중앙값을 사용하여 인풋하는 코드이다. 이 코드는 다음과 같은 단계로 이를 구현한다.
첫 번째 행은 DataFrame "df_product"를 "category_small_cd" 열로 그룹화하고 각 그룹의 "unit_price"와 "unit_cost"의 중앙값을 계산한다. 완성된 DataFrame의 이름은 "df_tmp"이며, 세 개의 컬럼을 가진다." category_small_cd", "median_price", "median_cost"의 세 개의 열을 가진다.
두 번째 행은 Pandas 라이브러리의 merge() 메서드를 사용하여 "category_small_cd" 컬럼을 기준으로 "df_product"와 "df_tmp" DataFrame을 결합하고 있다. 결과 DataFrame인 "df_product_4"는 "df_product"의 모든 컬럼과 "df_tmp"의 "median_price"와 "median_cost" 컬럼을 포함한다.
3번째 줄은 "df_product_4"에 "unit_price"라는 새로운 컬럼을 생성한다." "unit_price"와 "median_price" 열에 람다 함수를 적용하여 계산한다. 람다 함수는 "unit_price" 열이 존재하지 않는지(즉, NaN) 확인하고, 존재한다면 "median_price"의 반올림된 값을 반환한다. 그렇지 않은 경우 "unit_price"의 원래 값을 반환한다. 이 작업을 통해 "unit_price" 열의 누락된 값을 채운다.
4번째 줄은 "df_product_4"에 "unit_cost"라는 새로운 열을 생성한다." "unit_cost"와 "median_cost" 열에 유사한 람다 함수를 적용하여 계산된다. 이 작업은 "unit_cost" 열의 누락된 값을 채우는 것이다.
마지막 행은 isnull() 메서드와 sum() 메서드를 호출하여 "df_product_4" DataFrame에 여전히 누락된 값이 있는지 확인한다. 출력에 두 열 모두 결측값이 없는 것으로 나타나면, 인풋 연산이 성공한 것으로 확인된다.
# 코드 예시 2 (mask 활용)
df_tmp = (df_product.groupby('category_small_cd')
.agg(median_price=('unit_price', 'median'),
median_cost=('unit_cost', 'median')).reset_index())
df_product_4 = df_product.merge(df_tmp, how='inner', on='category_small_cd')
df_product_4['unit_price'] = (df_product_4['unit_price']
.mask(df_product_4['unit_price'].isnull(),
df_product_4['median_price'].round()))
df_product_4['unit_cost'] = (df_product_4['unit_cost']
.mask(df_product_4['unit_cost'].isnull(),
df_product_4['median_cost'].round()))
df_product_4.isnull().sum()
product_cd 0 category_major_cd 0 category_medium_cd 0 category_small_cd 0 unit_price 0 unit_cost 0 median_price 0 median_cost 0 dtype: int64
해설:
이 코드는 DataFrame "df_product"의 "unit_price"와 "unit_cost" 열의 결손된 값을 각 카테고리의 중앙값을 사용하여 인풋하는 코드이다. 이 코드는 다음과 같은 단계로 이를 구현한다.
첫 번째 행은 DataFrame "df_product"를 "category_small_cd" 열로 그룹화하고 각 그룹의 "unit_price"와 "unit_cost"의 중앙값을 계산한다. 완성된 DataFrame의 이름은 "df_tmp"이며, 세 개의 컬럼을 가진다." category_small_cd", "median_price", "median_cost"의 세 개의 열을 가진다.
두 번째 행은 Pandas 라이브러리의 merge() 메서드를 사용하여 "category_small_cd" 컬럼을 기준으로 "df_product"와 "df_tmp" DataFrame을 결합하고 있다. 결과 DataFrame인 "df_product_4"는 "df_product"의 모든 컬럼과 "df_tmp"의 "median_price"와 "median_cost" 컬럼을 포함한다.
3번째 행은 "df_product_4"에 Pandas의 mask() 메서드로 계산된 "unit_price"라는 새로운 컬럼을 생성하고 있습니다. 합니다. 이 작업으로 "unit_price" 열의 누락된 값이 채워진다.
4번째 줄은 "df_product_4"에 "unit_cost"라는 새로운 열을 만들고 "unit_price"와 같은 방식으로 계산한다. 이 작업을 통해 "unit_cost" 열의 결손된 값을 채운다.
마지막 행은 isnull() 메서드와 sum() 메서드를 호출하여 "df_product_4"의 DataFrame에 여전히 누락된 값이 있는지 확인한다. 출력에 두 열 모두 결손값이 없는 것으로 나타나면, 인풋 연산이 성공했음을 확인합니다.
# 코드 예시 3 (fillna, transform 활용)
df_product_4 = df_product.copy()
for x in ['unit_price', 'unit_cost']:
df_product_4[x] = (df_product_4[x]
.fillna(df_product_4.groupby('category_small_cd')[x]
.transform('median')
.round()))
df_product_4.isnull().sum()
product_cd 0 category_major_cd 0 category_medium_cd 0 category_small_cd 0 unit_price 0 unit_cost 0 dtype: int64
해설:
이 코드는 DataFrame "df_product"의 "unit_price"와 "unit_cost" 열의 결손된 값을 각 카테고리의 중앙값을 사용하여 인풋하는 코드이다. 이 코드는 다음과 같은 절차로 이를 구현한다.
첫 번째 줄은 원래 DataFrame "df_product"의 복사본을 만들고 "df_product_4"라는 이름을 붙인다.
두 번째 줄은 for 루프를 시작하여 'unit_price'와 'unit_cost' 컬럼에 대해 반복 처리를 수행한다.
세 번째 줄은 각 컬럼의 결손값을 채우고 있습니다. fillna() 메서드를 사용하여 각 열의 누락된 값을 각 카테고리의 중간값으로 대체하고 있습니다. 이는 'df_product_4'를 'category_small_cd' 열로 그룹화하고 transform() 메서드로 각 열의 중앙값을 계산하여 수행되며, round() 메서드는 중앙값을 가장 가까운 정수로 반올림하는 데 사용된다.
4번째 줄은 isnull() 메서드와 sum() 메서드를 호출하여 'df_product_4' DataFrame에 여전히 누락된 값이 있는지 확인한다. 출력에서 두 열 모두 결손값이 없는 것으로 나타나면, 인풋 연산이 성공한 것으로 확인된다.
이처럼 이 코드는 각 카테고리의 중앙값을 사용하여 DataFrame "df_product"의 "unit_price"와 "unit_cost" 열의 결손값을 입력한 후, 입력한 값으로 새로운 DataFrame "df_product_4"를 생성한다. 인풋은 원본 DataFrame을 복사하여 각 카테고리의 중앙값을 이용하여 각 열의 결손값을 채우고 결손값이 남았는지 확인하는 방식으로 이루어진다.
P-084: 고객 데이터(df_customer)의 전체 고객에 대해 전체 기간의 매출 금액에서 2019년 매출 금액이 차지하는 비율을 계산하여 새로운 데이터를 생성한다. 단, 매출 실적이 없는 경우 0으로 처리한다. 그리고 계산한 비율이 0을 초과하는 것을 추출하여 결과를 10건씩 표시하라. 또한, 작성된 데이터에 결손이 없는지 확인하라.
df_receipt_2019 = df_receipt.query('20190101 <= sales_ymd <= 20191231') \
.groupby('customer_id') \
.agg(amount_2019=('amount', 'sum')) \
.reset_index()
df_receipt_all = df_receipt.groupby('customer_id')\
.agg(amount_all=('amount', 'sum')) \
.reset_index()
df_sales_rate = df_customer[['customer_id']] \
.merge(df_receipt_2019, how='left', on='customer_id') \
.merge(df_receipt_all, how='left', on='customer_id')
df_sales_rate['amount_2019'] = df_sales_rate['amount_2019'].fillna(0)
df_sales_rate['amount_all'] = df_sales_rate['amount_all'].fillna(0)
df_sales_rate['amount_rate'] = \
df_sales_rate[['amount_2019','amount_all']] \
.apply(lambda x: 0 if x[0] == 0 else x[0] / x[1], axis=1)
df_sales_rate['amount_rate'] = df_sales_rate['amount_rate'].fillna(0)
df_sales_rate.query('amount_rate > 0').head(10)
customer_id | amount_2019 | amount_all | amount_rate | |
---|---|---|---|---|
2 | CS031415000172 | 2971.0 | 5088.0 | 0.583923 |
6 | CS015414000103 | 874.0 | 3122.0 | 0.279949 |
12 | CS011215000048 | 248.0 | 3444.0 | 0.072009 |
15 | CS029415000023 | 3767.0 | 5167.0 | 0.729050 |
21 | CS035415000029 | 5823.0 | 7504.0 | 0.775986 |
23 | CS023513000066 | 208.0 | 771.0 | 0.269780 |
24 | CS035513000134 | 463.0 | 1565.0 | 0.295847 |
27 | CS001515000263 | 216.0 | 216.0 | 1.000000 |
30 | CS006415000279 | 229.0 | 229.0 | 1.000000 |
32 | CS031415000106 | 215.0 | 7741.0 | 0.027774 |
df_tmp.isnull().sum()
category_small_cd 0 median_price 0 median_cost 0 dtype: int64
해설:
이 코드는 df_receipt라는 Pandas의 DataFrame에 대한 데이터 처리를 수행하여 2019년 고객의 총 매출 대비 매출 비율을 계산합니다. 아래는 이 코드가 무엇을 하는지 단계별로 설명합니다.
첫 번째 행은 df_receipt_2019라는 새로운 DataFrame을 생성하고, 2019년(20190101 <= sales_ymd <= 20191231)의 매출만 포함하도록 df_receipt의 행을 필터링합니다. 그리고 customer_id로 행을 그룹화하여 각 그룹의 금액 열의 합계를 계산합니다. 결과 DataFrame은 customer_id와 amount_2019의 두 개의 컬럼을 갖게 된다.
두 번째 행은 df_receipt_all이라는 새로운 DataFrame을 만들고, df_receipt의 행을 customer_id로 그룹화하여 각 그룹의 금액 컬럼의 합계를 계산한다. 완성된 DataFrame은 customer_id와 amount_all 두 개의 컬럼을 갖게 된다.
세 번째 행은 df_sales_rate라는 새로운 DataFrame을 만들어 df_customer의 customer_id 열을 df_receipt_2019와 df_receipt_all의 amount_2019 열과 amount_all 열에 각각 결합하고 있습니다. 즉, df_customer의 모든 행이 결과 DataFrame에 포함되지만, df_receipt_2019와 df_receipt_all의 일치하는 행만 포함된다. 결과 DataFrame에는 customer_id, amount_2019, amount_all의 세 개의 열이 있습니다.
4번째와 5번째 행에서는 amount_2019와 amount_all 열에서 누락된 값을 0으로 채운다.
6행은 amount_2019와 amount_all 열에 람다 함수를 적용하여 df_sales_rate에 amount_rate라는 새로운 열을 생성하고 있으며, λ 함수는 amount_2019가 0인 경우 0을, 그렇지 않은 경우 amount_2019와 amount_all의 비율을 반환합니다. 결과 column amount_rate 열은 각 고객의 총 매출과 비교하여 2019년의 매출 비율을 나타낸다.
7번째 줄은 amount_rate 열의 결손값을 0으로 채운다.
8행은 df_sales_rate 행을 필터링하여 양수 amount_rate를 가진 고객만 포함하도록 하고, DataFrame을 amount_rate로 내림차순으로 정렬하여 처음 10개의 행을 반환한다. 이들은 총 매출 대비 2019년 매출 비율이 가장 높은 상위 10명의 고객이다.
P-085: 고객 데이터(df_customer)의 모든 고객에 대해 우편번호(postal_cd)를 이용하여 지오코드 데이터(df_geocode)를 연결하여 새로운 고객 데이터를 생성한다. 단, 하나의 우편번호(postal_cd)에 여러 개의 경도(longitude), 위도(latitude) 정보가 연결된 경우에는 경도(longitude), 위도(latitude)의 평균값을 산출하여 사용해야 한다. 또한, 생성된 결과를 확인하기 위해 10개의 결과를 표시한다.
df_geocode_1 = df_geocode.groupby('postal_cd') \
.agg(m_longitude=('longitude', 'mean'),
m_latitude=('latitude', 'mean')).reset_index()
df_customer_1 = pd.merge(df_customer, df_geocode_1,
how='inner', on='postal_cd')
df_customer_1.head(10)
customer_id | customer_name | gender_cd | gender | birth_day | age | postal_cd | address | application_store_cd | application_date | status_cd | m_longitude | m_latitude | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | CS021313000114 | 大野 あや子 | 1 | 女性 | 1981-04-29 | 37 | 259-1113 | 神奈川県伊勢原市粟窪********** | S14021 | 20150905 | 0-00000000-0 | 139.31779 | 35.41358 |
1 | CS021303000023 | 堀 一徳 | 0 | 男性 | 1980-04-05 | 38 | 259-1113 | 神奈川県伊勢原市粟窪********** | S14021 | 20160411 | 0-00000000-0 | 139.31779 | 35.41358 |
2 | CS021303000007 | 石倉 俊二 | 0 | 男性 | 1987-07-04 | 31 | 259-1113 | 神奈川県伊勢原市粟窪********** | S14021 | 20150707 | 0-00000000-0 | 139.31779 | 35.41358 |
3 | CS021313000183 | 草野 未來 | 1 | 女性 | 1986-12-21 | 32 | 259-1113 | 神奈川県伊勢原市粟窪********** | S14021 | 20170611 | 0-00000000-0 | 139.31779 | 35.41358 |
4 | CS021314000098 | 筒井 れいな | 1 | 女性 | 1985-09-21 | 33 | 259-1113 | 神奈川県伊勢原市粟窪********** | S14021 | 20160901 | 0-00000000-0 | 139.31779 | 35.41358 |
5 | CS021314000093 | 江藤 美佐 | 1 | 女性 | 1986-06-03 | 32 | 259-1113 | 神奈川県伊勢原市粟窪********** | S14021 | 20151015 | 0-00000000-0 | 139.31779 | 35.41358 |
6 | CS021413000049 | 大野 幸子 | 1 | 女性 | 1973-04-17 | 45 | 259-1113 | 神奈川県伊勢原市粟窪********** | S14021 | 20150703 | 0-00000000-0 | 139.31779 | 35.41358 |
7 | CS037613000071 | 六角 雅彦 | 9 | 不明 | 1952-04-01 | 66 | 136-0076 | 東京都江東区南砂********** | S13037 | 20150414 | 0-00000000-0 | 139.83502 | 35.67193 |
8 | CS015415000209 | 大谷 倫子 | 1 | 女性 | 1970-11-25 | 48 | 136-0076 | 東京都江東区南砂********** | S13015 | 20150909 | B-20090610-C | 139.83502 | 35.67193 |
9 | CS037614000045 | 長沢 麻緒 | 1 | 女性 | 1952-06-19 | 66 | 136-0076 | 東京都江東区南砂********** | S13037 | 20150209 | 5-20091207-6 | 139.83502 | 35.67193 |
해설:
이 코드는 df_geocode와 df_customer라는 두 개의 Pandas DataFrame에 대해 데이터 처리를 수행합니다. 다음은 이 코드가 무엇을 하는지 단계별로 설명한다.
첫 번째 행은 df_geocode의 행을 postal_cd(우편번호)로 그룹화하고 각 그룹의 평균 경도와 위도를 계산하여 df_geocode_1이라는 새로운 DataFrame을 생성합니다. 완성된 DataFrame은 postal_cd, m_longitude, m_latitude의 세 개의 컬럼을 가진다.
두 번째 행은 df_customer와 df_geocode_1을 postal_cd 컬럼으로 병합하여 df_customer_1이라는 새로운 DataFrame을 생성합니다. 즉, 두 DataFrame에서 일치하는 값을 가진 행만 결과 DataFrame에 포함된다. 결과 DataFrame은 df_customer의 모든 컬럼과 df_geocode_1의 m_longitude와 m_latitude 컬럼을 포함한다.
3번째 줄은 .head(10) 메서드를 사용하여 결과 DataFrame(df_customer_1)의 처음 10개의 행을 표시하고 있다. 이는 고객 정보와 해당 우편번호의 평균 경도 및 위도 값을 포함하는 병합된 데이터 샘플을 보여줍니다.
P-086: 085에서 생성한 위도경도별 고객 데이터에 대해 회원 신청 매장 코드(application_store_cd)를 키로 매장 데이터(df_store)와 결합하라. 그리고 신청 매장의 위도(latitude)-경도 정보(longitude)와 고객 주소(address)의 위도-경도를 이용하여 신청 매장과 고객 주소의 거리(단위: km)를 구하고, 고객 ID(customer_id), 고객 주소(address), 매장 주소(address)와 함께 표시하라. 과 함께 표시하라. 계산식은 아래의 간단한 식을 사용하되, 그 외 정밀도가 높은 방식을 이용한 라이브러리를 사용해도 무방하다. 결과는 10건을 표시한다.
위도(라디안):φ경도(라디안):λ:거리L=6371∗arccos(sinφ1∗sinφ2+cosφ1∗cosφ2∗cos(λ1−λ2))
# 코드 예시 1
def calc_distance(x1, y1, x2, y2):
distance = 6371 * math.acos(math.sin(math.radians(x1))
* math.sin(math.radians(x2))
+ math.cos(math.radians(x1))
* math.cos(math.radians(x2))
* math.cos(math.radians(y1) - math.radians(y2)))
return distance
df_tmp = pd.merge(df_customer_1, df_store,
how='inner',
left_on='application_store_cd',
right_on='store_cd') \
.rename(columns={'address_x':'customer_address',
'address_y':'store_address'})
df_tmp['distance'] = df_tmp[['m_latitude',
'm_longitude',
'latitude',
'longitude']] \
.apply(lambda x: calc_distance(x[0], x[1], x[2], x[3]),
axis=1)
df_tmp[['customer_id', 'customer_address',
'store_address', 'distance']].head(10)
customer_id | customer_address | store_address | distance | |
---|---|---|---|---|
0 | CS021313000114 | 神奈川県伊勢原市粟窪********** | 神奈川県伊勢原市伊勢原四丁目 | 1.394409 |
1 | CS021303000023 | 神奈川県伊勢原市粟窪********** | 神奈川県伊勢原市伊勢原四丁目 | 1.394409 |
2 | CS021303000007 | 神奈川県伊勢原市粟窪********** | 神奈川県伊勢原市伊勢原四丁目 | 1.394409 |
3 | CS021313000183 | 神奈川県伊勢原市粟窪********** | 神奈川県伊勢原市伊勢原四丁目 | 1.394409 |
4 | CS021314000098 | 神奈川県伊勢原市粟窪********** | 神奈川県伊勢原市伊勢原四丁目 | 1.394409 |
5 | CS021314000093 | 神奈川県伊勢原市粟窪********** | 神奈川県伊勢原市伊勢原四丁目 | 1.394409 |
6 | CS021413000049 | 神奈川県伊勢原市粟窪********** | 神奈川県伊勢原市伊勢原四丁目 | 1.394409 |
7 | CS021313000025 | 神奈川県伊勢原市伊勢原********** | 神奈川県伊勢原市伊勢原四丁目 | 0.474282 |
8 | CS021413000022 | 神奈川県伊勢原市伊勢原********** | 神奈川県伊勢原市伊勢原四丁目 | 0.474282 |
9 | CS021413000094 | 神奈川県伊勢原市伊勢原********** | 神奈川県伊勢原市伊勢原四丁目 | 0.474282 |
해설:
이 코드는 df_customer_1, df_store, df_tmp라는 3개의 Pandas DataFrame에 대해 몇 가지 지리적 공간 계산과 데이터 처리를 수행한다. 여기서는 이 코드가 무엇을 하는지 단계별로 설명한다.
첫 번째 줄은 calc_distance라는 파이썬 함수를 정의하고 x1과 y1(점 1의 위도와 경도), x2와 y2(점 2의 위도와 경도)라는 4개의 인수를 취한다. 이 함수는 반경 6371km의 구형 지구를 가정하고 허버신의 공식을 사용하여 두 점 사이의 거리를 킬로미터 단위로 계산한다. 결과는 distance로 반환된다.
두 번째 행은 df_customer_1과 df_store를 각각 application_store_cd와 store_cd 컬럼으로 병합하여 df_tmp라는 새로운 DataFrame을 생성하고 있다. 즉, 두 DataFrame에서 일치하는 값을 가진 행만 결과 DataFrame에 포함된다. 결과 DataFrame은 두 DataFrame의 모든 컬럼을 가지고 있으며, 주소_x는 customer_address로, address_y는 store_address로 이름이 변경된 몇 개의 컬럼을 더 가지고 있다.
세 번째 줄은 .apply() 메서드를 사용하여 m_latitude, m_longitude, latitude, longitude 열에 calc_distance 함수를 적용하여 df_tmp에 distance라는 새로운 열을 생성하고 있다. .apply() 메서드는 axis=1 인자와 함께 함수를 행 단위로 적용하는 데 사용된다. 결과 거리 값은 distance 열에 저장된다.
4번째 줄은 이중 대괄호를 사용하여 df_tmp에서 컬럼의 일부(customer_id, customer_address, store_address, and distance)를 선택하고, .head(10) 메서드를 사용하여 결과 DataFrame의 처음 10개의 행을 표시하고 있습니다. 이는 고객 및 매장 정보가 포함된 병합된 데이터 샘플과 그 사이의 거리를 보여줍니다.
# 코드 예시 2
def calc_distance_numpy(x1, y1, x2, y2):
x1_r = np.radians(x1)
x2_r = np.radians(x2)
y1_r = np.radians(y1)
y2_r = np.radians(y2)
return 6371 * np.arccos(np.sin(x1_r) * np.sin(x2_r)
+ np.cos(x1_r) * np.cos(x2_r)
* np.cos(y1_r - y2_r))
df_tmp = df_customer_1.merge(df_store,
how='inner',
left_on='application_store_cd',
right_on='store_cd') \
.rename(columns={'address_x':'customer_address',
'address_y':'store_address'})
df_tmp['distance'] = calc_distance_numpy(df_tmp['m_latitude'],
df_tmp['m_longitude'],
df_tmp['latitude'],
df_tmp['longitude'])
df_tmp[['customer_id', 'customer_address',
'store_address', 'distance']].head(10)
customer_id | customer_address | store_address | distance | |
---|---|---|---|---|
0 | CS021313000114 | 神奈川県伊勢原市粟窪********** | 神奈川県伊勢原市伊勢原四丁目 | 1.394409 |
1 | CS021303000023 | 神奈川県伊勢原市粟窪********** | 神奈川県伊勢原市伊勢原四丁目 | 1.394409 |
2 | CS021303000007 | 神奈川県伊勢原市粟窪********** | 神奈川県伊勢原市伊勢原四丁目 | 1.394409 |
3 | CS021313000183 | 神奈川県伊勢原市粟窪********** | 神奈川県伊勢原市伊勢原四丁目 | 1.394409 |
4 | CS021314000098 | 神奈川県伊勢原市粟窪********** | 神奈川県伊勢原市伊勢原四丁目 | 1.394409 |
5 | CS021314000093 | 神奈川県伊勢原市粟窪********** | 神奈川県伊勢原市伊勢原四丁目 | 1.394409 |
6 | CS021413000049 | 神奈川県伊勢原市粟窪********** | 神奈川県伊勢原市伊勢原四丁目 | 1.394409 |
7 | CS021313000025 | 神奈川県伊勢原市伊勢原********** | 神奈川県伊勢原市伊勢原四丁目 | 0.474282 |
8 | CS021413000022 | 神奈川県伊勢原市伊勢原********** | 神奈川県伊勢原市伊勢原四丁目 | 0.474282 |
9 | CS021413000094 | 神奈川県伊勢原市伊勢原********** | 神奈川県伊勢原市伊勢原四丁目 | 0.474282 |
해설:
이 코드는 df_customer_1, df_store, df_tmp라는 3개의 Pandas DataFrame에 대해 몇 가지 지리적 공간 계산과 데이터 처리를 수행한다. 여기서는 이 코드가 무엇을 하는지 단계별로 설명한다.
첫 번째 줄은 calc_distance_numpy라는 파이썬 함수를 정의하고 x1과 y1(점 1의 위도와 경도), x2와 y2(점 2의 위도와 경도)라는 4개의 인수를 취한다. 이 함수는 반경 6371km의 구형 지구를 가정하고 허버신의 공식을 사용하여 두 점 사이의 거리를 킬로미터 단위로 계산한다. 이 구현에서는 NumPy 함수를 사용하여 이전 구현보다 더 효율적으로 계산을 수행합니다.
두 번째 행은 df_customer_1과 df_store를 각각 application_store_cd와 store_cd 열로 병합하여 df_tmp라는 새로운 DataFrame을 생성하고 있습니다. 즉, 두 DataFrame에서 일치하는 값을 가진 행만 결과 DataFrame에 포함된다. 결과 DataFrame은 두 DataFrame의 모든 컬럼을 가지고 있으며, 주소_x는 customer_address로, address_y는 store_address로 이름이 변경된 몇 개의 컬럼을 더 가지고 있다.
세 번째 줄은 df_tmp의 4개 열에 대해 NumPy의 배열 연산을 사용하여 calc_distance_numpy 함수를 호출하여 distance라는 새로운 열을 생성하고 있다. 이 구현에서는 .apply() 메서드를 사용하는 대신 NumPy의 배열에 대해 요소별 계산을 수행하는 기능을 활용하고 있습니다. 결과 거리 값은 distance 열에 저장됩니다.
4번째 줄은 이중 대괄호를 사용하여 df_tmp에서 컬럼의 하위 집합(customer_id, customer_address, store_address, and distance)을 선택하고 .head(10) 메서드를 사용하여 결과 DataFrame의 처음 10개의 행을 표시하고 있습니다. 이는 고객 및 매장 정보가 포함된 병합된 데이터 샘플과 그 사이의 해당 거리를 보여줍니다.
P-087: 고객 데이터(df_customer)에는 다른 매장에서의 신청 등으로 동일 고객이 여러 개 등록되어 있다. 이름(customer_name)과 우편번호(postal_cd)가 같은 고객은 동일 고객으로 간주하여 1고객 1레코드가 되도록 이름을 붙인 명목 고객 데이터를 생성하고, 고객 데이터 개수, 명목 고객 데이터 개수, 중복 횟수를 계산하라. 단, 동일 고객에 대해서는 매출 금액 합계가 가장 높은 것을 남기고, 매출 금액 합계가 동일하거나 매출 실적이 없는 고객에 대해서는 고객 ID(customer_id)의 번호가 작은 것을 남긴다.
df_receipt_tmp = df_receipt.groupby('customer_id') \
.agg(sum_amount=('amount','sum')).reset_index()
df_customer_u = pd.merge(df_customer, df_receipt_tmp,
how='left',
on='customer_id')
df_customer_u['sum_amount'] = df_customer_u['sum_amount'].fillna(0)
df_customer_u = df_customer_u.sort_values(['sum_amount', 'customer_id'],
ascending=[False, True])
df_customer_u.drop_duplicates(subset=['customer_name', 'postal_cd'],
keep='first', inplace=True)
print('df_customer_cnt:', len(df_customer),
'df_customer_u_cnt:', len(df_customer_u),
'diff:', len(df_customer) - len(df_customer_u))
df_customer_cnt: 21971 df_customer_u_cnt: 21941 diff: 30
해설:
이 코드는 다음과 같은 작업을 수행한다.
df_receipt 데이터 프레임을 customer_id로 그룹화하여 각 고객의 금액 합계를 계산한다. 결과 데이터 프레임은 df_receipt_tmp에 저장된다.
customer_id 열을 기준으로 df_customer 데이터 프레임을 df_receipt_tmp 데이터 프레임과 결합한다. 이것은 왼쪽 결합이므로 df_customer의 모든 고객이 결과 데이터 프레임 df_customer_u에 포함된다.
sum_amount 컬럼의 누락된 값을 0으로 대체합니다.
df_customer_u의 행을 sum_amount로 내림차순, customer_id로 오름차순으로 정렬합니다.
customer_name 열과 postal_cd 열을 기준으로 df_customer_u의 중복을 삭제하고 중복의 첫 번째 출현만 남겨둔다. 결과 데이터 프레임이 df_customer_u로 되돌아간다.
원래 df_customer 데이터 프레임의 행 수 (df_customer_cnt), 업데이트 후 df_customer_u 데이터 프레임의 행 수 (df_customer_u_cnt), 둘 사이의 차이 (diff)를 인쇄합니다.
전체적으로 이 코드는 데이터 정리와 조작을 통해 새로운 데이터 프레임 df_customer_u를 생성한다. 이 데이터 프레임에는 각 고객의 총 구매 금액(sum_amount)에 대한 정보가 포함되어 있으며, 이 금액에 따라 내림차순으로 정렬되고, customer_name과 postal_cd 열을 기준으로 중복되는 항목은 삭제됩니다.
P-088: 087에서 생성한 데이터를 바탕으로 고객 데이터에 통합명칭 ID를 부여한 데이터를 생성한다. 단, 통합명칭 ID는 아래의 사양으로 부여한다.
- 중복되지 않은 고객 : 고객 ID(customer_id) 설정
- 중복되는 고객: 이전 설문에서 추출한 레코드의 고객 ID를 설정한다.
고객 ID의 고유 건수와 통합명칭 ID의 고유 건수 차이도 확인해야 한다.
df_customer_n = pd.merge(df_customer,
df_customer_u[['customer_name',
'postal_cd', 'customer_id']],
how='inner', on =['customer_name', 'postal_cd'])
df_customer_n.rename(columns={'customer_id_x':'customer_id',
'customer_id_y':'integration_id'}, inplace=True)
print('ID 수의 차이', len(df_customer_n['customer_id'].unique())
- len(df_customer_n['integration_id'].unique()))
ID 수의 차이 30
해설:
이 코드는 df_customer와 df_customer_u라는 두 개의 데이터 프레임을 병합하여 이름과 우편번호를 기반으로 고유한 고객을 식별하고 일치시킨다.
병합된 결과 데이터 프레임은 df_customer_n이라는 새로운 데이터 프레임에 저장되며, merge 함수를 사용하여 두 데이터 프레임을 병합하고, on=['customer_name', 'postal_cd']라는 인수를 사용하여 이 두 열에 기반으로 병합할 것을 지정한다.
병합된 데이터 프레임에는 customer_id_x와 customer_id_y라는 두 개의 고객 ID 컬럼이 포함된다. 혼란을 피하기 위해 rename 함수를 사용하여 이 열의 이름을 각각 customer_id와 integration_id로 변경한다.
마지막 행에서 customer_id 열의 고유한 고객 ID 수와 integration_id 열의 고유한 고객 ID 수를 비교한다. 차이가 0이면 병합된 데이터 프레임에 중복된 고객이 없음을 의미합니다. 차이가 0이 아니라면 이름과 우편번호가 일치하지 않는 고객이 여전히 존재하고 그 ID가 중복되어 있음을 의미합니다.
P-closure: df_customer_1, df_customer_n은 사용하지 않으므로 삭제한다.
del df_customer_1
del df_customer_n
P-089: 예측 모델 구축을 위해 판매 실적이 있는 고객을 학습용 데이터와 테스트용 데이터로 나누고 싶다. 각각 8:2의 비율로 무작위로 데이터를 분할하라.
df_sales_customer = df_receipt.groupby('customer_id') \
.agg({'amount':sum}).reset_index()
df_sales_customer = df_sales_customer.query('amount > 0')
df_tmp = pd.merge(df_customer, df_sales_customer['customer_id'],
how='inner', on='customer_id')
df_train, df_test = train_test_split(df_tmp, test_size=0.2, random_state=71)
print('학습 데이터 비율: ', len(df_train) / len(df_tmp))
print('테스트 데이터 비율: ', len(df_test) / len(df_tmp))
학습 데이터 비율: 0.7999036840837949
테스트 데이터 비율: 0.20009631591620516
해설:
이 코드는 각 고객의 매출 정보를 기반으로 데이터 훈련 및 테스트 분할을 수행한다.
먼저 df_receipt dataframe을 customer_id로 그룹화하고 amount 열을 합산하여 각 고객의 매출 정보를 집계한다. 이렇게 얻은 데이터 프레임은 df_sales_customer에 저장된다.
그런 다음 쿼리 메소드를 사용하여 구매를 하지 않은 고객(즉, 금액이 0인 고객)을 필터링하고 df_sales_customer를 업데이트하여 이들 고객만 포함하도록 한다.
그런 다음 df_sales_customer의 customer_id 컬럼과 df_customer의 내부 결합을 수행하여 구매를 한 고객만 유지한다. 결과 데이터 프레임은 df_tmp에 저장된다.
마지막으로 scikit-learn의 train_test_split 메소드를 사용하여 df_tmp를 훈련 세트와 테스트 세트로 분할한다. 테스트 크기는 0.2, 랜덤 상태는 71이다. 그리고 훈련 세트와 테스트 세트에 포함된 데이터의 비율을 표시한다.
P-090: 영수증 내역 데이터(df_receipt)는 2017년 1월 1일부터 2019년 10월 31일까지의 데이터를 가지고 있다. 매출 금액(amount)을 월별로 집계하여 학습용 12개월, 테스트용 6개월의 시계열 모델 구축용 데이터 3세트를 생성한다.
# 코드 예시 1 (자작 함수)
df_ts_amount = df_receipt[['sales_ymd', 'amount']].copy()
df_ts_amount['sales_ym'] = df_ts_amount['sales_ymd'].astype('str').str[0:6]
df_ts_amount = df_ts_amount.groupby('sales_ym') \
.agg({'amount':'sum'}).reset_index()
# 장기간의 데이터에 대한 다수의 데이터 세트도 루프 등으로 처리할 수 있도록 기능화
def split_data(df, train_size, test_size, slide_window, start_point):
train_start = start_point * slide_window
test_start = train_start + train_size
return df[train_start:test_start], df[test_start:test_start + test_size]
df_train_1, df_test_1 = split_data(df_ts_amount, train_size=12,
test_size=6, slide_window=6, start_point=0)
df_train_2, df_test_2 = split_data(df_ts_amount, train_size=12,
test_size=6, slide_window=6, start_point=1)
df_train_3, df_test_3 = split_data(df_ts_amount, train_size=12,
test_size=6, slide_window=6, start_point=2)
# df_train_2와 df_train_3의 표시는 생략합니다.
df_train_1
sales_ym | amount | |
---|---|---|
0 | 201701 | 902056 |
1 | 201702 | 764413 |
2 | 201703 | 962945 |
3 | 201704 | 847566 |
4 | 201705 | 884010 |
5 | 201706 | 894242 |
6 | 201707 | 959205 |
7 | 201708 | 954836 |
8 | 201709 | 902037 |
9 | 201710 | 905739 |
10 | 201711 | 932157 |
11 | 201712 | 939654 |
해설:
이 코드는 다음과 같은 작업을 수행한다.
'sales_ymd', 'amount', 'sales_ym' 컬럼을 가진 df_ts_amount dataframe을 생성하고, sales_ym 컬럼은 sales_ymd 컬럼의 첫 6글자를 문자열로 변환하여 생성한다.
df_ts_amount 데이터 프레임을 'sales_ym' 컬럼으로 그룹화하고, 'sum' 함수로 'amount' 컬럼을 집계하여 인덱스를 재설정한다. 완성된 데이터 프레임은 동일한 변수 'df_ts_amount'에 저장된다.
split_data 함수는 df, train size, test size, slide window, start point를 인수로 취하며, split_data 함수는 train 데이터 프레임과 test 데이터 프레임 두 개의 데이터 프레임을 반환한다.
split_data 함수는 df_ts_amount 데이터 프레임을 train 데이터 프레임과 test 데이터 프레임으로 분할하기 위해 매번 다른 인수로 세 번 호출된다. 훈련 데이터와 테스트 데이터 세 세트가 생성되어 df_train_1, df_test_1, df_train_2, df_test_2, df_train_3, df_test_3에 저장된다.
데이터를 여러 개로 분할하는 목적은 시계열 예측 모델의 훈련 세트와 검증 세트로 사용하기 위한 것으로 보인다. 데이터를 여러 세트로 분할하면 모델을 다른 기간 동안 학습시키고 다른 테스트 기간 동안 성능을 평가할 수 있다. 이를 통해 오버피팅을 피하고 모델의 성능을 보다 정확하게 추정할 수 있다.
# df_test_2와 df_test_3의 표시는 생략합니다.
df_test_1
sales_ym | amount | |
---|---|---|
12 | 201801 | 944509 |
13 | 201802 | 864128 |
14 | 201803 | 946588 |
15 | 201804 | 937099 |
16 | 201805 | 1004438 |
17 | 201806 | 1012329 |
# 코드 예시 2 (scikit-learn의 TimeSeriesSplit)
tscv = TimeSeriesSplit(gap=0, max_train_size=12, n_splits=3, test_size=6)
# TimeSeriesSplit은 최신 데이터를 사용하도록 분할하지만
# SQL, R의 해답 예제와 동일하게 데이터 기간을 조정
# 최대한 최신 데이터를 사용하도록 한다면 불필요
df_ts_amount = df_ts_amount.query('sales_ym <= "201906"')
series_list = []
for train_index, test_index in tscv.split(df_ts_amount):
series_list.append((df_ts_amount.loc[train_index],
df_ts_amount.loc[test_index]))
df_train_1, df_test_1 = series_list[0]
df_train_2, df_test_2 = series_list[1]
df_train_3, df_test_3 = series_list[2]
# df_train_2와 df_train_3의 표시는 생략합니다.
df_train_1
sales_ym | amount | |
---|---|---|
0 | 201701 | 902056 |
1 | 201702 | 764413 |
2 | 201703 | 962945 |
3 | 201704 | 847566 |
4 | 201705 | 884010 |
5 | 201706 | 894242 |
6 | 201707 | 959205 |
7 | 201708 | 954836 |
8 | 201709 | 902037 |
9 | 201710 | 905739 |
10 | 201711 | 932157 |
11 | 201712 | 939654 |
# df_test_2와 df_test_3의 표시는 생략합니다.
df_test_1
sales_ym | amount | |
---|---|---|
12 | 201801 | 944509 |
13 | 201802 | 864128 |
14 | 201803 | 946588 |
15 | 201804 | 937099 |
16 | 201805 | 1004438 |
17 | 201806 | 1012329 |
해설:
이 코드는 pandas의 DataFrame df_ts_amount에 대해 시계열 교차 검증을 수행하고 있으며, sklearn.model_selection 모듈의 TimeSeriesSplit 함수를 사용하여 3개의 훈련과 테스트 분할을 생성하여 하고 있습니다.
TimeSeriesSplit은 시계열 데이터 샘플을 분할하기 위한 훈련/테스트 인덱스를 제공하는 교차 검증기이며, 4개의 파라미터를 가지고 있다.
n_splits: 분할 횟수
max_train_size: 학습 데이터의 최대 크기
test_size: 테스트 데이터의 크기
gap: 새로운 분할을 시작하기 전에 건너뛸 샘플 수
코드에서는 n_splits=3, max_train_size=12, test_size=6, gap=0으로 설정하여 학습 기간 12개월, 테스트 기간 6개월의 3분할을 생성한다.
다음 코드는 2019년 6월까지의 매출 데이터만 포함하도록 데이터를 필터링하고(df_ts_amount.query('sales_ym <= "201906"')), list series_list를 생성하여 TimeSeriesSplit에서 생성한 학습 세트와 테스트 세트를 저장한다. for 루프는 TimeSeriesSplit에 의해 생성된 분할을 반복하여 각 분할을 series_list에 추가하고 있다. 마지막으로 첫 번째 훈련과 테스트 분할을 df_train_1과 df_test_1에, 두 번째 분할을 df_train_2와 df_test_2에, 세 번째 분할을 df_train_3과 df_test_3에 할당하고 있다.
P-091: 고객 데이터(df_customer)의 각 고객에 대해 매출 실적이 있는 고객 수와 매출 실적이 없는 고객 수가 1:1이 되도록 언더샘플링으로 추출하라.
df_tmp = df_receipt.groupby('customer_id').agg({'amount':'sum'}).reset_index()
df_tmp = pd.merge(df_customer, df_tmp, how='left', on='customer_id')
df_tmp['is_buy_flag'] = np.where(df_tmp['amount'].isnull(), 0, 1)
rs = RandomUnderSampler(random_state=71)
df_down_sampling, _ = rs.fit_resample(df_tmp, df_tmp.is_buy_flag)
print('0의 건수', len(df_down_sampling.query('is_buy_flag == 0')))
print('1의 건수', len(df_down_sampling.query('is_buy_flag == 1')))
0의 건수 8306 1의 건수 8306
해설:
이 코드는 바이너리 대상 변수 is_buy_flag의 균형을 맞추기 위해 무작위 언더샘플링을 수행한다.
먼저 각 고객의 구매 금액 합계가 groupby를 사용하여 계산되어 df_tmp에 저장됩니다. 그런 다음 df_customer와 df_tmp는 왼쪽 결합을 사용하여 병합하여 구매를 하지 않았더라도 모든 고객을 포함하도록 하고, is_buy_flag 열은 np.where를 사용하여 구매를 한 고객에게는 1을, 구매를 하지 않은 고객에게는 0을 할당하여 생성한다. 생성됩니다.
그런 다음 imblearn 라이브러리의 RandomUnderSampler 함수를 사용하여 대상 변수의 균형을 맞추고, is_buy_flag 열을 대상 변수로 하는 fit_resample 메서드를 df_tmp에 적용한다. 이렇게 하면 두 대상 변수의 값에 대해 동일한 수의 케이스를 가진 새로운 DataFrame인 df_down_sampling이 생성된다.
마지막으로 is_buy_flag의 값이 0과 1인 경우의 수를 출력하여 랜덤 언더샘플링이 성공했음을 확인한다.
P-092: 고객 데이터(df_customer)의 성별을 제3정규형으로 정규화하라.
df_gender_std = df_customer[['gender_cd', 'gender']].drop_duplicates()
df_customer_std = df_customer.drop(columns='gender')
# 데이터 내용 확인
df_customer_std.head(3)
customer_id | customer_name | gender_cd | birth_day | age | postal_cd | address | application_store_cd | application_date | status_cd | |
---|---|---|---|---|---|---|---|---|---|---|
0 | CS021313000114 | 大野 あや子 | 1 | 1981-04-29 | 37 | 259-1113 | 神奈川県伊勢原市粟窪********** | S14021 | 20150905 | 0-00000000-0 |
1 | CS037613000071 | 六角 雅彦 | 9 | 1952-04-01 | 66 | 136-0076 | 東京都江東区南砂********** | S13037 | 20150414 | 0-00000000-0 |
2 | CS031415000172 | 宇多田 貴美子 | 1 | 1976-10-04 | 42 | 151-0053 | 東京都渋谷区代々木********** | S13031 | 20150529 | D-20100325-C |
# 데이터 내용 확인
df_gender_std.head(3)
gender_cd | gender | |
---|---|---|
0 | 1 | 女性 |
1 | 9 | 不明 |
5 | 0 | 男性 |
해설:
이 코드에서는 df_customer 데이터 프레임에서 'gender_cd'와 'gender' 열을 선택하고 drop_duplicates() 메서드를 사용하여 중복된 행을 삭제하여 df_gender_std를 생성하고 있다. 이렇게 하면 'gender_cd'와 'gender' 값의 고유한 조합으로 새로운 데이터 프레임이 생성됩니다.
df_customer_std는 df_customer dataframe에서 'gender' 열을 drop() 메서드를 사용하여 columns 파라미터를 'gender'로 설정하여 삭제함으로써 생성된다. 이렇게 하면 df_customer에서 'gender' 컬럼을 제외한 모든 컬럼을 가진 새로운 dataframe이 생성된다.
이 코드의 목적은 'gender_cd'와 'gender'의 고유한 조합을 가진 데이터 프레임과 df_customer의 'gender'를 제외한 모든 컬럼을 가진 데이터 프레임을 별도로 생성하는 것이다. 이러한 데이터 프레임은 추가 분석 및 모델링에 사용할 수 있다.
P-093: 상품 데이터(df_product)는 각 카테고리의 코드 값만 보유하고 카테고리 이름은 보유하지 않는다. 카테고리 데이터(df_category)와 결합하여 비정규화하여 카테고리 이름을 보유한 새로운 상품 데이터를 생성한다.
df_product_full = pd.merge(df_product, df_category[['category_small_cd',
'category_major_name',
'category_medium_name',
'category_small_name']],
how = 'inner', on = 'category_small_cd')
# 데이터 내용 확인
df_product_full.head(3)
product_cd | category_major_cd | category_medium_cd | category_small_cd | unit_price | unit_cost | category_major_name | category_medium_name | 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 | 惣菜 | 御飯類 | 弁当類 |
해설:
이 코드는 두 데이터 프레임 df_product와 df_category 사이에서 category_small_cd 컬럼으로 내부 바인딩을 수행한다. 결과 df_product_full은 df_product와 df_category의 모든 컬럼을 포함하며, 결합은 category_small_cd의 일치하는 값을 기반으로 한다.
새로운 데이터 프레임 df_product_full에는 df_category의 추가 컬럼, 특히 category_major_name, category_medium_name, category_small_name도 포함되어 있다. 이 열들은 상품 카테고리에 대한 카테고리 정보를 담고 있으며, 두 데이터 프레임에서 일치하는 값을 가진 행만 유지하는 how='inner' 옵션을 사용하여 병합된 데이터 프레임에 포함된다. .head(3) 메서드는 병합된 데이터 프레임의 처음 세 행을 표시하는 데 사용된다.
P-094: 093에서 생성한 카테고리명 상품데이터를 다음과 같은 사양으로 파일 출력한다.
|파일 형식| 헤더 유무| 문자 인코딩|
|:–:|:–:|:–:|
CSV(쉼표로 구분) | 있음 | UTF-8|
# 코드 예시 1
# 답안 파일의 위치가 문제 파일과 다르기 때문에 경로가 '. /data'로 되어 있는 점 참고
df_product_full.to_csv('../data/P_df_product_full_UTF-8_header.csv',
encoding='UTF-8', index=False)
해설:
이 코드는 Pandas의 DataFrame df_product_full을 파일 경로와 파일명을 지정하여 CSV 파일 . /data/P_df_product_full_UTF-8_header.csv로 내보내고 있습니다. 내보내는 CSV 파일은 다양한 문자를 지원하기 위해 UTF-8 인코딩을 사용하며, index=False 인수는 DataFrame의 행 인덱스를 내보내는 CSV 파일에 포함하지 않도록 지정합니다.
# 코드 예시 2 (BOM이 있는 엑셀의 깨진 문자 방지)
df_product_full.to_csv('../data/P_df_product_full_UTF-8BOM_header.csv',
encoding='utf_8_sig', index=False)
해설:
이 코드는 df_product_full의 DataFrame을 P_df_product_full_UTF-8BOM_header.csv라는 파일명으로 CSV 파일로 내보내고 있다.
pandas DataFrame의 to_csv() 메서드는 DataFrame의 내용을 CSV 파일로 작성하는 데 사용됩니다. 이 메서드에는 파일 이름과 사용할 인코딩 등 몇 가지 파라미터가 있습니다.
이 경우, filename 매개변수에는 '. /data/P_df_product_full_UTF-8BOM_header.csv'로 설정되어 있으며, CSV 파일의 디렉토리와 파일명을 지정합니다. . /data/' 접두사는 파일을 저장할 상대적인 디렉토리를 지정한다.
encoding 매개변수에는 CSV 파일에 사용할 인코딩 형식을 지정하는 'utf_8_sig'가 설정되며, 'utf_8_sig'는 파일 시작 부분에 바이트 순서 표시(BOM)를 포함하는 UTF-8 인코딩의 일종이다. 순서를 나타내는 특수 마커로, 파일을 열 때 프로그램이 인코딩 형식을 판단하는 데 도움이 된다.
index 매개 변수는 False로 설정되어 DataFrame의 인덱스를 CSV 파일에 포함하지 않도록 지정한다.
P-095: 093에서 생성한 카테고리명 상품 데이터를 아래 사양으로 파일 출력하라.
|파일 형식| 헤더 유무| 문자 인코딩|
|:–:|:–:|:–:|
CSV(쉼표로 구분) | 있음 |CP932|
출력처 경로를 다음과 같이 설정한다.
|출력처||:–:||./data|
# 답안 파일의 위치가 문제 파일과 다르기 때문에 경로가 '. /data'로 되어 있는 점 참고
df_product_full.to_csv('../data/P_df_product_full_CP932_header.csv',
encoding='CP932', index=False)
해설:
이 코드는 pandas의 DataFrame인 df_product_full을 ". /data/' 디렉토리에 있는 'P_df_product_full_CP932_header.csv'라는 이름의 CSV 파일로 내보내고 있습니다.
내보낸 CSV 파일은 'Windows-31J'라고도 불리는 일본어 문자 인코딩인 'CP932' 문자 인코딩을 사용합니다. 이 인코딩은 일본에서 텍스트 데이터에 자주 사용되는 인코딩으로 Windows 운영 체제와 호환됩니다.
parameter encoding='CP932'는 CSV 파일을 내보낼 때 사용할 문자 인코딩을 지정한다.
index=False 매개 변수는 내보낸 CSV 파일에 index 컬럼을 포함하지 않도록 지정합니다.
P-096: 093에서 생성한 카테고리명 상품 데이터를 아래 사양으로 파일 출력하라.
|파일 형식| 헤더 유무| 문자 인코딩|
|:–:|:–:|:–:|
CSV(쉼표로 구분) | 없음 |CP932|
출력처 경로를 다음과 같이 설정한다.
|출력처||:–:||./data|
# 답안 파일의 위치가 문제 파일과 다르기 때문에 경로가 '. /data'로 되어 있는 점 참고
df_product_full.to_csv('../data/P_df_product_full_UTF-8_noh.csv',
header=False, encoding='UTF-8', index=False)
해설:
df_product_full DataFrame을 ". /data/" 디렉토리의 "P_df_product_full_UTF-8_noh.csv"라는 CSV 파일에 저장하는 코드이다.
첫 번째 인수에는 CSV 파일을 저장할 파일명과 경로를 지정하고, header 인수는 False로 설정하여 DataFrame의 헤더 라인이 출력 파일에 포함되지 않음을 의미하며, encoding 인수는 'UTF-8'로 설정하여 파일 쓰기 시 사용할 문자 인코딩을 지정한다. 문자 인코딩을 지정한다. 이는 DataFrame의 인덱스가 출력 파일에 포함되지 않음을 의미합니다.
전체적으로 이 코드는 df_product_full DataFrame을 UTF-8 인코딩으로 CSV 파일로 내보내는데, 헤더 라인은 포함되지 않는다.
P-097: 094에서 생성한 아래 형식의 파일을 불러와서 데이터 3건을 표시하여 제대로 입력되었는지 확인하라
|파일 형식| 헤더 유무| 문자 인코딩|
|:–:|:–:|:–:|
CSV(쉼표로 구분) | 있음 |UTF-8|
출력처 경로를 다음과 같이 설정한다.
|출력처||:–:||./data|
# 답안 파일의 위치가 문제 파일과 다르기 때문에 경로가 '. /data'로 되어 있는 점 참고
df_product_full = pd.read_csv('../data/P_df_product_full_UTF-8_header.csv',
dtype={'category_major_cd':str,
'category_medium_cd':str,
'category_small_cd':str},
encoding='UTF-8')
df_product_full.head(3)
product_cd | category_major_cd | category_medium_cd | category_small_cd | unit_price | unit_cost | category_major_name | category_medium_name | 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 | 惣菜 | 御飯類 | 弁当類 |
해설:
위 코드는 UTF-8 인코딩으로 헤더 행이 없는 CSV 파일 P_df_product_full_UTF-8_no.csv를 읽고 데이터 프레임에 열 이름을 할당하고 있습니다.
pd.read_csv('... /data/P_df_product_full_UTF-8_noh.csv', dtype={1:str, 2:str, 3:str}, encoding='UTF-8', header=None): 헤더 라인이 없는 CSV 파일을 불러와 2열, 3열, 4열을 문자열 데이터 타입으로 설정한다. 결과 데이터 프레임에는 0, 1, 2, 3, 4, 5, 6, 7, 8이라는 이름의 열이 있습니다.
df_product_full.columns = ['product_cd', 'category_major_cd', 'category_medium_cd', 'category_small_cd', 'unit_price', 'unit_cost',' category_major_name', 'category_medium_name', 'category_small_name']: 데이터 프레임의 컬럼에 새로운 컬럼 이름을 부여한다. 결과 데이터 프레임은 product_cd, category_major_cd, category_major_cd, category_medium_cd, category_small_cd, unit_price, unit_cost, category_major_name, category_medium_name, and category_small_name 열을 가진다.
df_product_full.head(3): df_product_full의 처음 세 줄을 표시한다.
P-098: 096에서 생성한 아래 형식의 파일을 불러와서 데이터 3건을 표시하여 제대로 입력되었는지 확인한다.
|파일 형식| 헤더 유무| 문자 인코딩|
|:–:|:–:|:–:|
CSV(쉼표로 구분) | 없음 |UTF-8|
# 코드 예시 1 (나중에 항목 이름 붙이기)
# 답안 파일의 위치가 문제 파일과 다르기 때문에 경로가 '. /data'로 되어 있는 점 참고
df_product_full = pd.read_csv('../data/P_df_product_full_UTF-8_noh.csv',
dtype={1:str,
2:str,
3:str},
encoding='UTF-8', header=None)
df_product_full.columns = ['product_cd','category_major_cd',
'category_medium_cd', 'category_small_cd',
'unit_price','unit_cost','category_major_name',
'category_medium_name', 'category_small_name']
df_product_full.head(3)
product_cd | category_major_cd | category_medium_cd | category_small_cd | unit_price | unit_cost | category_major_name | category_medium_name | 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 | 惣菜 | 御飯類 | 弁当類 |
해설:
이 코드는 '. /data' 디렉터리에 있는 'P_df_product_full_UTF-8_noh.csv'라는 이름의 CSV 파일을 불러오며, 'names' 파라미터는 'c_names'라는 문자열 목록으로 사용하며, 'dtype' 파라미터는 'category_major_cd', 'category_medium_cd', 'category_small_cd'라는 이름의 열에 대한 데이터, 'category_major_cd', 'category_medium_cd', 'category_small_cd'라는 이름의 컬럼의 데이터 타입을 'str'(문자열)로 지정한다. 될 것을 지정한다. 마지막으로 'header' 매개변수는 파일에 헤더 행이 없음을 나타내기 위해 'None'으로 설정한다.
완성된 데이터 프레임은 'df_product_full' 변수에 할당되고, 'head' 메서드를 사용하여 처음 세 줄을 표시한다.
# 코드 예시 2 (항목명을 먼저 정의한다)
c_names = ['product_cd','category_major_cd','category_medium_cd',
'category_small_cd','unit_price','unit_cost',
'category_major_name','category_medium_name','category_small_name']
df_product_full = pd.read_csv('../data/P_df_product_full_UTF-8_noh.csv',
names=c_names,
dtype={'category_major_cd':str,
'category_medium_cd':str,
'category_small_cd':str},
encoding='UTF-8', header=None)
df_product_full.head(3)
product_cd | category_major_cd | category_medium_cd | category_small_cd | unit_price | unit_cost | category_major_name | category_medium_name | 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 | 惣菜 | 御飯類 | 弁当類 |
해설:
이 코드는 read_csv 함수를 사용하여 CSV 파일을 사용자 정의된 컬럼 이름을 가진 Pandas DataFrame에 불러오는 코드입니다.
다음은 코드에 대한 설명입니다.
c_names: 커스터마이징된 컬럼 이름을 정의하는 문자열 목록입니다.
pd.read_csv(): CSV 파일을 읽어와 DataFrame을 반환하는 Pandas 함수입니다.
'... /data/P_df_product_full_UTF-8_noh.csv': 불러올 CSV 파일의 파일 경로입니다.
names=c_names: c_names 목록을 사용하여 사용자 정의한 컬럼 이름을 지정합니다.
dtype={'category_major_cd':str, 'category_medium_cd':str, 'category_small_cd':str}: category_major_cd, category_medium_cd, category_small_cd, category_small_cd small_cd 컬럼의 데이터 타입을 str로 지정한다.
encoding='UTF-8': 파일의 인코딩을 'UTF-8'로 지정한다.
header=None: CSV 파일에 헤더 라인이 없음을 지정한다.
마지막으로 head() 메서드를 사용하여 결과 DataFrame을 표시하고 처음 세 줄을 표시합니다.
P-099: 093에서 생성한 카테고리명 상품 데이터를 아래 사양으로 파일 출력하라.
|파일 형식| 헤더 유무| 문자 인코딩|
|:–:|:–:|:–:|
TSV(탭으로 구분) | 있음 |UTF-8|
출력처 경로를 다음과 같이 설정한다.
|출력처||:–:||./data|
# 답안 파일의 위치가 문제 파일과 다르기 때문에 경로가 '. /data'로 되어 있는 점 참고
df_product_full.to_csv('../data/P_df_product_full_UTF-8_header.tsv',
sep='\t', encoding='UTF-8', index=False)
해설:
이 코드는 df_product_full이라는 pandas의 DataFrame의 내용을 '. /d/P_df_product_full_UTF-8_header.tsv'에 있는 TSV(Tab-Separated Values) 파일에 작성합니다.
.to_csv() 메서드는 df_product_full DataFrame에 대해 호출되며, 데이터를 CSV (Comma-Separated Values) 또는 TSV 파일로 내보내기 위해 pandas가 제공하는 방법이다.
메서드의 첫 번째 인수인 '. /d/P_df_product_full_UTF-8_header.tsv'는 DataFrame을 저장할 파일 경로와 파일 이름이다. 파일은 . /d/ 디렉토리에 P_df_product_full_UTF-8_header.tsv라는 이름으로 저장됩니다.
두 번째 인수 sep='˶'는 파일 내 값을 쉼표 대신 탭으로 구분하도록 지정한다.
세 번째 인수 encoding='UTF-8'은 파일의 인코딩을 유니코드 문자의 표준 인코딩인 UTF-8로 지정한다.
네 번째 인수 index=False는 DataFrame의 인덱스를 출력 파일에 포함하지 않도록 지정한다.
P-100: 099에서 생성한 아래 형식의 파일을 불러와서 데이터 3건을 표시하여 제대로 입력되었는지 확인한다.
|파일 형식| 헤더 유무| 문자 인코딩|
|:–:|:–:|:–:|
TSV(탭으로 구분) | 있음 |UTF-8|
# 코드 예시 1 (read_table)
# 답안 파일의 위치가 문제 파일과 다르기 때문에 경로가 '. /data'로 되어 있는 점 참고
df_product_full = pd.read_table('../data/P_df_product_full_UTF-8_header.tsv',
dtype={'category_major_cd':str,
'category_medium_cd':str,
'category_small_cd':str},
encoding='UTF-8')
df_product_full.head(3)
product_cd | category_major_cd | category_medium_cd | category_small_cd | unit_price | unit_cost | category_major_name | category_medium_name | 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 | 惣菜 | 御飯類 | 弁当類 |
해설:
이 코드에서는 '. /data/P_df_product_full_UTF-8_header.tsv'에 있는 TSV(Tab-Separated Values) 파일에서 df_product_full이라는 pandas DataFrame에 데이터를 불러오고 있습니다.
파일에서 데이터를 불러오기 위해 pd.read_table() 함수가 호출됩니다. 함수의 첫 번째 인자인 '. /data/P_df_product_full_UTF-8_header.tsv'는 읽을 파일의 경로와 이름을 지정합니다.
함수의 두 번째 인수인 dtype={'category_major_cd':str, 'category_medium_cd':str, 'category_small_cd':str}는 DataFrame의 특정 열의 데이터 타입을 지정한다. 구체적으로 category_major_cd, category_medium_cd, category_small_cd의 각 열을 string(str) 타입으로 설정한다.
이 함수의 세 번째 인수 encoding='UTF-8'은 파일의 인코딩이 UTF-8임을 지정한다.
그리고 완성된 DataFrame인 df_product_full을 head(3) 메서드로 표시하면 DataFrame의 첫 3행이 표시된다.
# 코드 예시 2 (read_csv)
df_product_full = pd.read_csv('../data/P_df_product_full_UTF-8_header.tsv',
dtype={'category_major_cd':str,
'category_medium_cd':str,
'category_small_cd':str},
sep='\t', encoding='UTF-8')
df_product_full.head(3)
product_cd | category_major_cd | category_medium_cd | category_small_cd | unit_price | unit_cost | category_major_name | category_medium_name | 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 | 惣菜 | 御飯類 | 弁当類 |
설명:
이 코드에서는 '. /data/P_df_product_full_UTF-8_header.tsv'에 있는 TSV(Tab-Separated Values) 파일에서 df_product_full이라는 pandas DataFrame에 데이터를 불러오고 있습니다.
파일에서 데이터를 불러오기 위해 pd.read_csv() 함수가 호출됩니다. 함수의 첫 번째 인수인 '. /data/P_df_product_full_UTF-8_header.tsv'는 읽을 파일의 경로와 이름을 지정합니다.
함수의 두 번째 인수인 dtype={'category_major_cd':str, 'category_medium_cd':str, 'category_small_cd':str}는 DataFrame의 특정 열의 데이터 타입을 지정한다. 구체적으로 category_major_cd, category_medium_cd, category_small_cd의 각 열을 string(str) 타입으로 설정하고 있다.
세 번째 인수 sep='˶'는 파일 내 값을 쉼표가 아닌 탭으로 구분할 것을 지정한다.
네 번째 인수 encoding='UTF-8'은 파일의 인코딩이 UTF-8임을 지정한다.
그리고 완성된 DataFrame인 df_product_full을 head(3) 메서드로 표시하면 DataFrame의 첫 3행이 표시된다.
Comment