Chapter 07-3~5 여러 열을 하나로 정리하기, 중복 데이터 처리하기, 대용량 데이터 처리하기
여러 열을 하나로 정리하기
보통 데이터프레임의 열은 파이썬의 변수와 같은 개념으로 사용합니다. 하지만 비슷한 성질의 데이터를 관리하기 위해 열이 여러 개로 분리되어 있는 경우도 있습니다. 다음 실습을 통해 여러 개로 분리된 열을 정리하는 방법에 대해 알아보겠습니다.
기상 데이터의 여러 열을 하나로 정리하기 - melt, pibot_table 메서드
1. 다음은 기상 데이터를 불러와 출력한 것입니다. 날짜 열(d1, ..., d31)에는 각 월별 최고, 최저 온도 데이터가 저장되어 있습니다. 지금은 날짜 열이 옆으로 길게 늘어져 있어 보기 불편합니다. 먼저 날짜 열을 행 데이터로 피벗하겠습니다.
weather = pd.read_csv('../data/weather.csv') print(weather.iloc[:5, :]) id year month element d1 d2 d3 d4 d5 d6 d7 ... 0 MX17004 2010 1 tmax NaN NaN NaN NaN NaN NaN NaN 1 MX17004 2010 1 tmin NaN NaN NaN NaN NaN NaN NaN 2 MX17004 2010 2 tmax NaN 27.3 24.1 NaN NaN NaN NaN 3 MX17004 2010 2 tmin NaN 14.4 14.4 NaN NaN NaN NaN 4 MX17004 2010 3 tmax NaN NaN NaN NaN 32.1 NaN NaN |
2. 다음은 melt 메서드로 일별 온도 측정값(d1, d2, ...)을 피벗한 것입니다. 그러면 day 열에 날짜 열이 정리되고 날짜 열의 데이터는 temp 열에 정리됩니다. 하지만 아직 최고, 최저 온도가 한눈에 잘 들어오지 않습니다.
weather_melt = pd.melt(weather, id_vars=['id', 'year', 'month', 'element'], var_name='day', value_name='temp') print(weather_melt.head( )) id year month element day temp 0 MX17004 2010 1 tmax d1 NaN 1 MX17004 2010 1 tmin d1 NaN 2 MX17004 2010 2 tmax d1 NaN 3 MX17004 2010 2 tmin d1 NaN 4 MX17004 2010 3 tmax d1 NaN |
3. 이제 pivot_table 메서드를 사용할 차례입니다. pivot_table 메서드는 행과 열의 위치를 다시 바꿔 정리해 줍니다. index 인자에는 위치를 그대로 유지할 열 이름을 지정하고, columns 인자에는 피벗할 열 이름을 지정하고, values 인자에는 새로운 열의 데이터가 될 열 이름을 지정하면 됩니다. 다음은 pivot_table 메서드로 행과 열의 위치를 다시 바꾼 것입니다. 과정 2의 실행 결과를 비교하여 살펴보세요.
weather_tidy = weather_melt.pivot_table( index=['id', 'year', 'month', 'day'], columns='element', values='temp', dropna=False) print(weather_tidy) element tmax tmin id year month day MX17004 2010 1 d1 NaN NaN d10 NaN NaN ... ... ... 12 d10 NaN NaN d11 NaN NaN ... d7 NaN NaN d8 NaN NaN d9 NaN NaN [321 rows x 2 columns] |
4. 다음은 과정 3에서 구한 데이터프레임의 인덱스를 reset_index 메서드로 새로 지정한 것입니다.
weather_tidy_flat = weather_tidy.reset_index( ) print(weather_tidy_flat.head( )) element id year month day tmax tmin 0 MX17004 2010 1 d1 NaN NaN 1 MX17004 2010 1 d10 NaN NaN 2 MX17004 2010 1 d11 NaN NaN 3 MX17004 2010 1 d12 NaN NaN 4 MX17004 2010 1 d13 NaN NaN |
중복 데이터 처리하기
이번에 다룰 빌보드 차트 데이터는 artist, track, time, date.entered 열의 데이터가 반복됩니다. 이런 반복되는 데이터는 따로 관리하는 것이 좋습니다. 왜 따로 관리하는 것이 좋을까요? 그리고 따로 관리하려면 어떻게 해야 할까요? 다음 실습을 통해 중복 데이터를 처리하는 방법에 대해 알아보겠습니다.
빌보드 차트의 중복 데이터 처리하기
1. 다음은 빌보드 차트 데이터를 불러온 것입니다.
billboard = pd.read_csv('../data/billboard.csv') billboard_long = pd.melt(billboard, id_vars=['year', 'artist', 'track', 'time', 'date.entered'], var_name='week', value_name='rating') print(billboard_long.shape) (24092, 7) print(billboard_long.head( )) year artist track time date.entered week rating 0 2000 2Pac Baby Don't Cry (Keep... 4:22 2000-02-26 wk1 87.0 1 2000 2Ge+her The Hardest Part of ... 3:15 2000-09-02 wk1 91.0 2 2000 3 Doors Down Kryptonite 3:53 2000-04-08 wk1 81.0 3 2000 3 Doors Down Loser 4:24 2000-10-21 wk1 76.0 4 2000 504 Boyz Wobble Wobble 3:35 2000-04-15 wk1 57.0 |
2. 노래 제목(track)이 Loser인 데이터만 따로 모아 살펴보면 중복 데이터가 꽤 많다는 것을 알 수 있습니다. 예를 들어 가수(artist)는 고유한 값이기 때문에 따로 관리하는 것이 데이터의 일관성을 유지하는 데 더 도움이 됩니다.
print(billboard_long[billboard_long.track == 'Loser'].head( )) year artist track time date.entered week rating 3 2000 3 Doors Down Loser 4:24 2000-10-21 wk1 76.0 320 2000 3 Doors Down Loser 4:24 2000-10-21 wk2 76.0 637 2000 3 Doors Down Loser 4:24 2000-10-21 wk3 72.0 954 2000 3 Doors Down Loser 4:24 2000-10-21 wk4 69.0 1271 2000 3 Doors Down Loser 4:24 2000-10-21 wk5 67.0 |
3. 중복 데이터를 가지고 있는 열은 year, artist, track, time, date입니다. 이 열을 따로 모아 새로운 데이터프레임에 저장합니다.
billboard_songs = billboard_long[['year', 'artist', 'track', 'time']] print(billboard_songs.shape) (24092, 4) |
4. 그런 다음 drop_duplicates 메서드로 데이터프레임의 중복 데이터를 제거합니다.
billboard_songs = billboard_songs.drop_duplicates( ) print(billboard_songs.shape) (317, 4) |
5. 중복을 제거한 데이터프레임에 다음과 같이 아이디(id)도 추가합니다.
billboard_songs['id'] = range(len(billboard_songs)) print(billboard_songs.head(n=10)) year artist track time id 0 2000 2Pac Baby Don't Cry (Keep... 4:22 0 1 2000 2Ge+her The Hardest Part of ... 3:15 1 2 2000 3 Doors Down Kryptonite 3:53 2 3 2000 3 Doors Down Loser 4:24 3 4 2000 504 Boyz Wobble Wobble 3:35 4 5 2000 98^0 Give Me Just One Nig... 3:24 5 6 2000 A*Teens Dancing Queen 3:44 6 7 2000 Aaliyah I Don't Wanna 4:15 7 8 2000 Aaliyah Try Again 4:03 8 9 2000 Adams, Yolanda Open My Heart 5:30 9 |
6. 다음은 merge 메서드를 사용해 노래 정보와 주간 수위 데이터를 합친 것입니다.
billboard_ratings = billboard_long.merge(billboard_songs, on=['year', 'artist', 'track', 'time']) print(billboard_ratings.shape) (2409, 8) print(billboard_ratings.head( )) year artist track time date.entered week rating id 0 2000 2Pac Baby Don't Cry (Keep... 4:22 2000-02-26 wk1 87.0 0 1 2000 2Pac Baby Don't Cry (Keep... 4:22 2000-02-26 wk2 82.0 0 2 2000 2Pac Baby Don't Cry (Keep... 4:22 2000-02-26 wk3 72.0 0 3 2000 2Pac Baby Don't Cry (Keep... 4:22 2000-02-26 wk4 77.0 0 4 2000 2Pac Baby Don't Cry (Keep... 4:22 2000-02-26 wk5 87.0 0 |
대용량 데이터 처리하기
여러 개로 나누어진 데이터 불러오기
데이터는 필요에 따라 나누어 저장하기도 합니다. 데이터를 나누어 저장하면 용량이 작아져 데이터를 저장하거나 다른 사람에게 공유할 때 유용하죠. 또 어떤 경우에는 처음부터 크기가 작은 데이터가 생성되는 경우도 있습니다. 예를 들어 주식 정보를 매일 수집한다면 일 단위로 데이터가 생성됩니다. 지금까지는 한 덩어리의 데이터를 불러와 여러 가지 실습을 진행했습니다. 그러면 여러 개로 나누어진 데이터를 신속하게 불러오려면 어떻게 해야 할까요? 그리고 이런 데이터를 다루는 방법은 무엇일까요?
뉴욕 택시 데이터 준비하기
뉴욕 택시 데이터는 13억 대의 뉴욕 택시에 대한 정보를 가지고 있습니다. 파일의 개수도 140개나 됩니다. 이번 실습에서는 이 중 5개의 데이터만 사용해 보겠습니다.
1. 다음을 입력하여 실행한 후 데이터를 내려받습니다. 네트워크 상태에 따라 5 ~ 15분이 소요됩니다.
import os import urllib.request with open('../data/raw_data_urls.txt', 'r') as data_urls: for line, url in enumerate(data_urls): if line == 5: break fn = url.split('/')[-1].strip() fp = os.path.join('', '../data', fn) print(url) print(fp) urllib.request.urlretrieve(url, fp) |
2. 내려받은 데이터는 data 폴더에 'fhv_tripdata_YYYY_MM.csv'라는 이름으로 저장됩니다. 이제 판다스로 데이터를 불러오면 됩니다. glob 라이브러리에 포함된 glob 메서드는 특정한 패턴의 이름을 가진 파일을 한 번에 읽어 들일 수 있습니다. glob 메서드로 5개의 파일을 불러옵니다.
import glob nyc_taxi_data = glob.glob('../data/fhv_*') print(nyc_taxi_data) ['../data\\fhv_tripdata_2015-01.csv', '../data\\fhv_tripdata_2015-02.csv', '../data\\fhv_tripdata_2015-03.csv', '../data\\fhv_tripdata_2015-04.csv', '../data\\fhv_tripdata_2015-05.csv'] |
3. 그런 다음 각각의 파일을 데이터프레임으로 저장합니다.
taxi1 = pd.read_csv(nyc_taxi_data[0]) taxi2 = pd.read_csv(nyc_taxi_data[1]) taxi3 = pd.read_csv(nyc_taxi_data[2]) taxi4 = pd.read_csv(nyc_taxi_data[3]) taxi5 = pd.read_csv(nyc_taxi_data[4]) |
4. 데이터를 잘 볼러왔는지 확인합니다.
print(taxi1.head(n=2)) print(taxi2.head(n=2)) print(taxi3.head(n=2)) print(taxi4.head(n=2)) print(taxi5.head(n=2)) Dispatching_base_num Pickup_date locationID 0 B00013 2015-01-01 00:30:00 NaN 1 B00013 2015-01-01 01:22:00 NaN Dispatching_base_num Pickup_date locationID 0 B00013 2015-02-01 00:00:00 NaN 1 B00013 2015-02-01 00:01:00 NaN Dispatching_base_num Pickup_date locationID 0 B00029 2015-03-01 00:02:00 NaN 1 B00029 2015-03-01 00:03:00 NaN Dispatching_base_num Pickup_date locationID 0 B00001 2015-04-01 04:30:00 NaN 1 B00001 2015-04-01 06:00:00 NaN Dispatching_base_num Pickup_date locationID 0 B00001 2015-05-01 04:30:00 NaN 1 B00001 2015-05-01 05:00:00 NaN |
5. 각 데이터의 구조, 즉 행과 열을 확인해 보겠습니다. 데이터가 꽤 크다는 것을 알 수 있습니다.
print(taxi1.shape) print(taxi2.shape) print(taxi3.shape) print(taxi4.shape) print(taxi5.shape) (2746033, 3) (3126401, 3) (3281427, 3) (3917789, 3) (4296067, 3) |
6. 이제 데이터 처리를 위해 각 데이터프레임을 연결해야 합니다. 다음은 concat 메서드로 모든 데이터프레임(taxi1~5)을 연결한 것입니다.
taxi = pd.concat([taxi1, taxi2, taxi3, taxi4, taxi5]) print(taxi.shape) (17367717, 3) |
* 반복문으로 데이터 준비하기
반복문을 응용하면 단 몇 줄의 코드로 데이터를 준비할 수 있습니다. 앞의 실습에서 생성한 파일 목록(nyc_taxi_data)을 반복문으로 읽어 들인 다음 리스트(list_taxi_df)에 이어붙이면 됩니다. 그러면 리스트에 데이터프레임이 순서대로 저장됩니다.
list_taxi_df = [] for csv_filename in nyc_taxi_data: # print(csv_filename) df = pd.read_csv(csv_filename) list_taxi_df.append(df) print(len(list_taxi_df)) 5 print(type(list_taxi_df[0])) <class 'pandas.core.frame.DataFrame'> print(list_taxi_df[0].head( )) Dispatching_base_num Pickup_date locationID 0 B00013 2015-01-01 00:30:00 NaN 1 B00013 2015-01-01 01:22:00 NaN 2 B00013 2015-01-01 01:23:00 NaN 3 B00013 2015-01-01 01:44:00 NaN 4 B00013 2015-01-01 02:00:00 NaN taxi_loop_concat = pd.concat(list_taxi_df) print(taxi_loop_concat.shape) (17367717, 3) print(taxi.equals(taxi_loop_concat)) True |
마무리하며
이 장에서는 깔끔한 데이터를 만드는 방법에 대해 알아보았습니다. 넓은 데이터를 분석하기 좋은 형태로 만들기 위한 피벗부터 중복 데이터를 처리하는 방법과 여러 열을 하나로 합치는 실습까지 진행해 보았습니다. 데이터 분석에서 깔끔한 데이터는 매우 중요합니다. 반드시 07장에서 공부한 내용을 완벽하게 이해하고 다음 장으로 넘어가세요.
출처 : "판다스 입문"