데이터 파편화 문제 - 명시적인 키변수가 있는 경우

2021-07-11

.

Data_Preprocessing_TIL(20210711)

[학습자료]

패스트캠퍼스 온라인 강의 “파이썬을 활용한 데이터 전처리 Level UP 올인원 패키지 Online.” 를 공부하고 정리한 내용입니다.

URL : https://fastcampus.co.kr/data_online_preprocess

[학습내용]

  • 명시적인 키변수가 있는 경우란

효율적인 데이터베이스 관리를 위해, 가공이 잘 된 데이터임에도 불구하고 데이터가 키 변수를 기준으로 나뉘어져 있는 경우가 흔하다.

  • 해결방안

SQL에서는 JOIN을 이용하여 해결하며, python에서는 merge를 이용해서 해결한다.

1

일반적인 경우는 이런식으로 해결하면 되지만 케이스 바이 케이스이기 때문에 반드시 아래의 두개의 원칙을 기억해야 한다.

원칙 1. 어떤게 키인지 명확하게 확인해야 한다.

어느 컬럼이 키 변수 역할을 하는지 확인하고, 키변수를 통일해야 한다.

원칙 2. 레코드 단위를 명확하게 해야 한다.

  • 위에 문제를 해결하기 위해 많이 쓰는 pandas.merge 함수

키변수를 기준으로 두개의 데이터 프레임을 join하는 함수

주요입력

1) left : 병합대상 데이터 프레임 1

2) right : 병합대상 데이터 프레임 2

3) on : 통합기준 key 변수 및 변수리스트

입력하지 않으면 이름이 같은 변수를 key로 식별하기 때문에 명시를 해주는게 좋다.

4) left_on : 데이터 프레임 1의 key 변수 및 변수리스트

5) right_on : 데이터 프레임 2의 key 변수 및 변수리스트

6) left_index : 데이터 프레임 1의 인덱스를 key 변수로 사용할지 여부

7) right_index : 데이터 프레임 2의 인덱스를 key 변수로 사용할지 여부

  • 실습

Telco_churn_customer_churn.csv과 Telco_churn_customer_info.csv을 join 해보자

# data 불러오기
import os
import pandas as pd

os.chdir(r"C:/Users/user/Desktop/aa/part-4.-머신러닝을-위한-필수-전처리/Part 4. 머신러닝을 위한 필수 전처리/데이터/")

df1 = pd.read_csv("Telco_churn_customer_churn.csv")
df1
customerID Churn
0 7590-VHVEG No
1 5575-GNVDE No
2 3668-QPYBK Yes
3 7795-CFOCW No
4 9237-HQITU Yes
... ... ...
7038 6840-RESVB No
7039 2234-XADUH No
7040 4801-JZAZL No
7041 8361-LTMKD Yes
7042 3186-AJIEK No

7043 rows × 2 columns

df2 = pd.read_csv("Telco_churn_customer_info.csv")
df2
customerID gender SeniorCitizen Partner Dependents tenure PhoneService MultipleLines InternetService OnlineSecurity OnlineBackup DeviceProtection TechSupport StreamingTV StreamingMovies Contract PaperlessBilling PaymentMethod MonthlyCharges TotalCharges
0 7590-VHVEG Female 0 Yes No 1 No No phone service DSL No Yes No No No No Month-to-month Yes Electronic check 29.85 29.85
1 5575-GNVDE Male 0 No No 34 Yes No DSL Yes No Yes No No No One year No Mailed check 56.95 1889.5
2 3668-QPYBK Male 0 No No 2 Yes No DSL Yes Yes No No No No Month-to-month Yes Mailed check 53.85 108.15
3 7795-CFOCW Male 0 No No 45 No No phone service DSL Yes No Yes Yes No No One year No Bank transfer (automatic) 42.30 1840.75
4 9237-HQITU Female 0 No No 2 Yes No Fiber optic No No No No No No Month-to-month Yes Electronic check 70.70 151.65
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
7038 6840-RESVB Male 0 Yes Yes 24 Yes Yes DSL Yes No Yes Yes Yes Yes One year Yes Mailed check 84.80 1990.5
7039 2234-XADUH Female 0 Yes Yes 72 Yes Yes Fiber optic No Yes Yes No Yes Yes One year Yes Credit card (automatic) 103.20 7362.9
7040 4801-JZAZL Female 0 Yes Yes 11 No No phone service DSL Yes No No No No No Month-to-month Yes Electronic check 29.60 346.45
7041 8361-LTMKD Male 1 Yes No 4 Yes Yes Fiber optic No No No No No No Month-to-month Yes Mailed check 74.40 306.6
7042 3186-AJIEK Male 0 No No 66 Yes No Fiber optic Yes No Yes Yes Yes Yes Two year Yes Bank transfer (automatic) 105.65 6844.5

7043 rows × 20 columns

customerID라는 명확한 키변수가 있는 것을 확인했다 그래서 merge on을 활용해서 join이 가능하다.

# 두 데이터프레임에서 이름이 같은 변수가 key 변수만 있더라도, on을 사용하는 것이 바람직함
merged_df = pd.merge(df1, df2, on = 'customerID') 
merged_df
customerID Churn gender SeniorCitizen Partner Dependents tenure PhoneService MultipleLines InternetService ... OnlineBackup DeviceProtection TechSupport StreamingTV StreamingMovies Contract PaperlessBilling PaymentMethod MonthlyCharges TotalCharges
0 7590-VHVEG No Female 0 Yes No 1 No No phone service DSL ... Yes No No No No Month-to-month Yes Electronic check 29.85 29.85
1 5575-GNVDE No Male 0 No No 34 Yes No DSL ... No Yes No No No One year No Mailed check 56.95 1889.5
2 3668-QPYBK Yes Male 0 No No 2 Yes No DSL ... Yes No No No No Month-to-month Yes Mailed check 53.85 108.15
3 7795-CFOCW No Male 0 No No 45 No No phone service DSL ... No Yes Yes No No One year No Bank transfer (automatic) 42.30 1840.75
4 9237-HQITU Yes Female 0 No No 2 Yes No Fiber optic ... No No No No No Month-to-month Yes Electronic check 70.70 151.65
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
7038 6840-RESVB No Male 0 Yes Yes 24 Yes Yes DSL ... No Yes Yes Yes Yes One year Yes Mailed check 84.80 1990.5
7039 2234-XADUH No Female 0 Yes Yes 72 Yes Yes Fiber optic ... Yes Yes No Yes Yes One year Yes Credit card (automatic) 103.20 7362.9
7040 4801-JZAZL No Female 0 Yes Yes 11 No No phone service DSL ... No No No No No Month-to-month Yes Electronic check 29.60 346.45
7041 8361-LTMKD Yes Male 1 Yes No 4 Yes Yes Fiber optic ... No No No No No Month-to-month Yes Mailed check 74.40 306.6
7042 3186-AJIEK No Male 0 No No 66 Yes No Fiber optic ... No Yes Yes Yes Yes Two year Yes Bank transfer (automatic) 105.65 6844.5

7043 rows × 21 columns

이번에는 left_on과 right_on을 이용해서 join을 해보자

# 연습을 위해 df2의 customerID 컬럼명을 ID로 변환해보자
df2.rename({"customerID":"ID"}, axis = 1, inplace = True) 
df2
ID gender SeniorCitizen Partner Dependents tenure PhoneService MultipleLines InternetService OnlineSecurity OnlineBackup DeviceProtection TechSupport StreamingTV StreamingMovies Contract PaperlessBilling PaymentMethod MonthlyCharges TotalCharges
0 7590-VHVEG Female 0 Yes No 1 No No phone service DSL No Yes No No No No Month-to-month Yes Electronic check 29.85 29.85
1 5575-GNVDE Male 0 No No 34 Yes No DSL Yes No Yes No No No One year No Mailed check 56.95 1889.5
2 3668-QPYBK Male 0 No No 2 Yes No DSL Yes Yes No No No No Month-to-month Yes Mailed check 53.85 108.15
3 7795-CFOCW Male 0 No No 45 No No phone service DSL Yes No Yes Yes No No One year No Bank transfer (automatic) 42.30 1840.75
4 9237-HQITU Female 0 No No 2 Yes No Fiber optic No No No No No No Month-to-month Yes Electronic check 70.70 151.65
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
7038 6840-RESVB Male 0 Yes Yes 24 Yes Yes DSL Yes No Yes Yes Yes Yes One year Yes Mailed check 84.80 1990.5
7039 2234-XADUH Female 0 Yes Yes 72 Yes Yes Fiber optic No Yes Yes No Yes Yes One year Yes Credit card (automatic) 103.20 7362.9
7040 4801-JZAZL Female 0 Yes Yes 11 No No phone service DSL Yes No No No No No Month-to-month Yes Electronic check 29.60 346.45
7041 8361-LTMKD Male 1 Yes No 4 Yes Yes Fiber optic No No No No No No Month-to-month Yes Mailed check 74.40 306.6
7042 3186-AJIEK Male 0 No No 66 Yes No Fiber optic Yes No Yes Yes Yes Yes Two year Yes Bank transfer (automatic) 105.65 6844.5

7043 rows × 20 columns

df1.head()
customerID Churn
0 7590-VHVEG No
1 5575-GNVDE No
2 3668-QPYBK Yes
3 7795-CFOCW No
4 9237-HQITU Yes

위와 같이 df2의 customerID가 ID로 바뀐것을 확인할 수 있다.

이때 그러면 pd.merge(df1, df2, on = ‘customerID’) 이거를 쓰게되면

df1에는 customerID가 있는데 df2에는 없어서 제대로 병합이 되지 않을것이다.

이럴때 사용하는게 left_on과 right_on 이다.

어떤 컬럼을 기준으로 병합할건지 명시해서 병합하는 방법이다.

# left, right 순서를 반드시 고려해야 함
# on, left_on, right_on 키워드에 리스트 형태로 입력받을 수 있음 (여기서도 순서가 중요)
merged_df = pd.merge(df1, df2, left_on = ['customerID'], right_on = ['ID']) 

# 키 컬럼 두 개가 모두 살아있음
merged_df
customerID Churn ID gender SeniorCitizen Partner Dependents tenure PhoneService MultipleLines ... OnlineBackup DeviceProtection TechSupport StreamingTV StreamingMovies Contract PaperlessBilling PaymentMethod MonthlyCharges TotalCharges
0 7590-VHVEG No 7590-VHVEG Female 0 Yes No 1 No No phone service ... Yes No No No No Month-to-month Yes Electronic check 29.85 29.85
1 5575-GNVDE No 5575-GNVDE Male 0 No No 34 Yes No ... No Yes No No No One year No Mailed check 56.95 1889.5
2 3668-QPYBK Yes 3668-QPYBK Male 0 No No 2 Yes No ... Yes No No No No Month-to-month Yes Mailed check 53.85 108.15
3 7795-CFOCW No 7795-CFOCW Male 0 No No 45 No No phone service ... No Yes Yes No No One year No Bank transfer (automatic) 42.30 1840.75
4 9237-HQITU Yes 9237-HQITU Female 0 No No 2 Yes No ... No No No No No Month-to-month Yes Electronic check 70.70 151.65
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
7038 6840-RESVB No 6840-RESVB Male 0 Yes Yes 24 Yes Yes ... No Yes Yes Yes Yes One year Yes Mailed check 84.80 1990.5
7039 2234-XADUH No 2234-XADUH Female 0 Yes Yes 72 Yes Yes ... Yes Yes No Yes Yes One year Yes Credit card (automatic) 103.20 7362.9
7040 4801-JZAZL No 4801-JZAZL Female 0 Yes Yes 11 No No phone service ... No No No No No Month-to-month Yes Electronic check 29.60 346.45
7041 8361-LTMKD Yes 8361-LTMKD Male 1 Yes No 4 Yes Yes ... No No No No No Month-to-month Yes Mailed check 74.40 306.6
7042 3186-AJIEK No 3186-AJIEK Male 0 No No 66 Yes No ... No Yes Yes Yes Yes Two year Yes Bank transfer (automatic) 105.65 6844.5

7043 rows × 22 columns

# 키 컬럼 중 하나를 삭제해줘야 함
merged_df.drop('ID', axis = 1, inplace = True)
merged_df.head()
customerID Churn gender SeniorCitizen Partner Dependents tenure PhoneService MultipleLines InternetService ... OnlineBackup DeviceProtection TechSupport StreamingTV StreamingMovies Contract PaperlessBilling PaymentMethod MonthlyCharges TotalCharges
0 7590-VHVEG No Female 0 Yes No 1 No No phone service DSL ... Yes No No No No Month-to-month Yes Electronic check 29.85 29.85
1 5575-GNVDE No Male 0 No No 34 Yes No DSL ... No Yes No No No One year No Mailed check 56.95 1889.5
2 3668-QPYBK Yes Male 0 No No 2 Yes No DSL ... Yes No No No No Month-to-month Yes Mailed check 53.85 108.15
3 7795-CFOCW No Male 0 No No 45 No No phone service DSL ... No Yes Yes No No One year No Bank transfer (automatic) 42.30 1840.75
4 9237-HQITU Yes Female 0 No No 2 Yes No Fiber optic ... No No No No No Month-to-month Yes Electronic check 70.70 151.65

5 rows × 21 columns