-
[CHAPTER 12] 데이터 분석 | pandasDeep Learning/인공지능 입문 코딩 2021. 6. 3. 18:18728x90
pandas는 파이썬 데이터 처리를 위한 라이브러리이다. 데이터 분석과 같은 작업에서 필수적인 라이브러리이니 자세히 살펴보도록 하자.
pandas의 특징
빠르고 효율적이며 다양한 표현력을 갖춘 자료구조
실세계 데이터 분석을 위해 만들어진 파이썬 패키지
다양한 형태의 데이터에 적합
이종(heterogeneous) 자료형의 열을 가진 테이블 데이터
시계열 데이터
레이블을 가진 다양한 행렬 데이터
다양한 관측 통계 데이터
핵심 구조
시리즈(Series) : 레이블이 붙어있는 1차원 벡터
데이터 프레임(DataFrame) : 행과 열로 되어있는 2차원 테이블, 각 열은 시리즈로 되어 있다.

이들 데이터 구조는 모두 넘파이 배열을 이용하여 구현된다.
행의 이름을 Index
열의 이름을 columns 라고 부른다.
기본적인 사용법
아래 데이터를 토대로 DataFrame을 만들어보자.
이름 나이 성별 평점 김수안 19 여 4.35 김수정 23 여 4.23 박동윤 22 남 4.45 강이안 19 여 4.37 강지안 16 남 4.25 >>> import pandas as pd >>> import numpy as np >>> name_series = pd.Series(['김수안', '김수정', '박동윤', '강이안', '강지안']) >>> age_series = pd.Series([19, 23, 22, 19, 16]) >>> sex_series = pd.Series(['여', '여', '남', '여', '남']) >>> grade_series = pd.Series([4.35, 4.23, 4.25, 4.37, 4.25]) >>> df = pd.DataFrame({ '이름': name_series, '나이': age_series, '성별': sex_series, '평점': grade_series}) >>> df 이름 나이 성별 평점 0 김수안 19 여 4.35 1 김수정 23 여 4.23 2 박동윤 22 남 4.25 3 강이안 19 여 4.37 4 강지안 16 남 4.25각 열에 대한 데이터를 pd.Series()로 만들고
Series를 기반으로 DataFrame()을 만든다.
DataFrame()을 호출할 때 이름 나이 성별 평점을 key로 하고 series들을 value로 하는 딕셔너리를 인자로 전달해 준다.
이미 만들어져 있는 csv파일을 읽어올 수도 있는데 그 방법을 살펴보자.
먼저 '따라하며 배우는 파이썬과 데이터 과학'의 저자의 github에서 데이터 파일을 다운로드하여오자.
https://github.com/dongupak/DataSciPy/blob/master/data/csv/countries.csv

countries.csv pd.read_csv() 함수를 이용한다. 첫 번째 인자는 경로, index_col에 0을 넘겨주면 0번째 열이 인덱스로 사용된다.
import pandas as pd countries_df = pd.read_csv('../data/countries.csv', index_col=0) print(countries_df)country area capital population
KR Korea 98480 Seoul 51780579
US USA 9629091 Washington 331002825
JP Japan 377835 Tokyo 125960000
CN China 9596960 Beijing 1439323688
RU Russia 17100000 Moscow 146748600원하는 데이터 선택하기
특정 열만 선택하려면 대괄호 안에 열의 이름을 넣어주면 된다.
>>> countries_df['country'] KR Korea US USA JP Japan CN China RU Russia Name: country, dtype: object특정 행을 선택하려면 loc['index']를 이용한다.
>>> countries_df.loc['KR'] country Korea area 98480 capital Seoul population 51780579 Name: KR, dtype: object앞의 5행만 얻고 싶을 때는 head()를 사용한다. 뒤의 5행을 얻으려면 tail()을 같은 방식으로 사용하면 된다.
데이터가 5행 밖에 없어서 차이가 없는 걸로 보인다.. ㅋ
>>> countries_df.head() country area capital population KR Korea 98480 Seoul 51780579 US USA 9629091 Washington 331002825 JP Japan 377835 Tokyo 125960000 CN China 9596960 Beijing 1439323688 RU Russia 17100000 Moscow 146748600>>> countries_df.tail() country area capital population KR Korea 98480 Seoul 51780579 US USA 9629091 Washington 331002825 JP Japan 377835 Tokyo 125960000 CN China 9596960 Beijing 1439323688 RU Russia 17100000 Moscow 146748600슬라이싱을 이용할 수도 있다.
>>> countries_df[:3] country area capital population KR Korea 98480 Seoul 51780579 US USA 9629091 Washington 331002825 JP Japan 377835 Tokyo 125960000위의 것들을 활용하여 써보자
열과 행을 결합하여 선택할 수 있다.
>>> countries_df['population'][:3] KR 51780579 US 331002825 JP 125960000 Name: population, dtype: int64loc 함수에 행과 열의 레이블을 함께 써주면 특정한 요소 하나만 선택할 수 있다.
>>> countries_df.loc['US', 'capital'] 'Washington'해당 열을 선택하고 loc함수로 행을 선택할 수도 있다.
>>> countries_df['capital'].loc['US'] 'Washington'데이터 추가
인구 밀도를 새로운 열로 추가하고 싶다.
아래와 같이 하면 된다. 쉽다. 설명할 필요도 없는 듯
import pandas as pd countries_df = pd.read_csv('../data/countries.csv', index_col=0) countries_df['density'] = countries_df['population'] / countries_df['area'] print(countries_df)country area capital population density
KR Korea 98480 Seoul 51780579 525.797918
US USA 9629091 Washington 331002825 34.375293
JP Japan 377835 Tokyo 125960000 333.373033
CN China 9596960 Beijing 1439323688 149.977044
RU Russia 17100000 Moscow 146748600 8.581789
데이터 분석
기상청에서 2010년 ~ 2020년까지 울릉도의 기온, 최대풍속, 풍속의 데이터를 기록한 데이터를 다운로드하여오자.
https://github.com/dongupak/DataSciPy/blob/master/data/csv/weather.csv
이러한 데이터가 3000천 개가 넘게 있는데 맨 위의 6개 정도만 캡처 해왔다.

waether.csv 먼저 pandas로 읽어 들이자.
한글이 들어있기 때문에 encoding='CP949'를 추가로 써주었다.
>>> import pandas as pd >>> weather_df = pd.read_csv('../data/weather.csv', encoding='CP949', index_col=0) >>> weather_df 평균기온 최대풍속 평균풍속 일시 2010-08-01 28.7 8.3 3.4 2010-08-02 25.2 8.7 3.8 2010-08-03 22.1 6.3 2.9 2010-08-04 25.3 6.6 4.2 2010-08-05 27.2 9.1 5.6 ... ... ... 2020-07-27 22.1 4.2 1.7 2020-07-28 21.9 4.5 1.6 2020-07-29 21.6 3.2 1.0 2020-07-30 22.9 9.7 2.4 2020-07-31 25.7 4.8 2.5 [3653 rows x 3 columns]describe()
전체적으로 데이터를 간단하게 분석하려면 describe() 함수를 사용하면 된다.
데이터의 개수(count), 평균값(mean), 표준편차(std), 최솟값(min), 최댓값(max) 등을 알 수 있다.
>>> weather_df.describe() 평균기온 최대풍속 평균풍속 count 3653.000000 3649.000000 3647.000000 mean 12.942102 7.911099 3.936441 std 8.538507 3.029862 1.888473 min -9.000000 2.000000 0.200000 25% 5.400000 5.700000 2.500000 50% 13.800000 7.600000 3.600000 75% 20.100000 9.700000 5.000000 max 31.300000 26.000000 14.900000count(), mean(), std(), min(), max()를 사용하여 하나만을 분석할 수도 있다.
>>> weather_df.max() 평균기온 31.3 최대풍속 26.0 평균풍속 14.9 dtype: float64사용 방법은 다 똑같다. 그러니 생략.
10년간 데이터 중에 평균 풍속 중 가장 높은 값을 가져오려면 아래와 같이 한다.
>>> weather_df['평균풍속'].max() 14.9이러한 방식으로 다양하게 데이터를 분석할 수 있다.
그룹핑
데이터를 특정한 값에 기반하여 그룹으로 묶는 방법을 알아보자.
아래의 데이터를 월별로 묶어 평균값을 내 보고 싶은데 천천히 살펴보자.
>>> import pandas as pd >>> weather_df = pd.read_csv('../data/weather.csv', encoding='CP949') >>> weather_df 일시 평균기온 최대풍속 평균풍속 0 2010-08-01 28.7 8.3 3.4 1 2010-08-02 25.2 8.7 3.8 2 2010-08-03 22.1 6.3 2.9 3 2010-08-04 25.3 6.6 4.2 4 2010-08-05 27.2 9.1 5.6 ... ... ... ... 3648 2020-07-27 22.1 4.2 1.7 3649 2020-07-28 21.9 4.5 1.6DatetimIndex
먼저 날짜를 표시하는 방식으로 된 데이터를 DatetimeIndex 객체로 다룰 수 있다.
DatetimeIndex에 대해 자세히 살펴보자
>>> datetimeIndex = pd.DatetimeIndex(weather_df['일시']) >>> datetimeIndex DatetimeIndex(['2010-08-01', '2010-08-02', '2010-08-03', '2010-08-04', '2010-08-05', '2010-08-06', '2010-08-07', '2010-08-08', '2010-08-09', '2010-08-10', ... '2020-07-22', '2020-07-23', '2020-07-24', '2020-07-25', '2020-07-26', '2020-07-27', '2020-07-28', '2020-07-29', '2020-07-30', '2020-07-31'], dtype='datetime64[ns]', name='일시', length=3653, freq=None)DatetimeIndex 객체에서 연도, 달, 일을 뽑아 올 수 있는데 방법은 아래와 같다.
>>> datetimeIndex.year Int64Index([2010, 2010, 2010, 2010, 2010, 2010, 2010, 2010, 2010, 2010, ... 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020], dtype='int64', name='일시', length=3653) >>> datetimeIndex.month Int64Index([8, 8, 8, 8, 8, 8, 8, 8, 8, 8, ... 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], dtype='int64', name='일시', length=3653) >>> datetimeIndex.day Int64Index([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ... 22, 23, 24, 25, 26, 27, 28, 29, 30, 31], dtype='int64', name='일시', length=3653)이제 DatetimeIndex 객체를 활용하여 weather.csv를 분석해보자.
weather.csv 월별로 묶기
새로운 열 month를 생성하고 해당하는 달을 기록한다.
new_df에 month가 같은 값끼리 묶어 평균을 내어 저장한다.
import pandas as pd weather_df = pd.read_csv('../data/weather.csv', encoding='CP949') weather_df['month'] = pd.DatetimeIndex(weather_df['일시']).month new_df = weather_df.groupby('month').mean() print(new_df) 평균기온 최대풍속 평균풍속 month 1 1.598387 8.158065 3.757419 2 2.136396 8.225357 3.946786 3 6.250323 8.871935 4.390291 4 11.064667 9.305017 4.622483 5 16.564194 8.548710 4.219355 6 19.616667 6.945667 3.461000 7 23.328387 7.322581 3.877419 8 24.748710 6.853226 3.596129 9 20.323667 6.896333 3.661667 10 15.383871 7.766774 3.961613 11 9.889667 8.013333 3.930667 12 3.753548 8.045484 3.817097필터링
weather.csv 에서 초속 10m/s 이상의 강풍이 불었던 날들을 찾아보고 싶을 때 아래와 같은 방법으로 할 수 있다.
weather_df[weather_df['최대풍속'] >= 10.0] 일시 평균기온 최대풍속 평균풍속 9 2010-08-10 25.6 10.2 5.5 12 2010-08-13 24.3 10.9 4.6 13 2010-08-14 25.0 10.8 4.4 14 2010-08-15 24.5 16.9 10.3 29 2010-08-30 26.2 10.5 6.2 ... ... ... ... 3622 2020-07-01 16.8 19.7 8.7 3632 2020-07-11 20.1 10.3 4.1 3634 2020-07-13 17.8 10.3 4.6 3635 2020-07-14 17.8 12.7 9.4 3641 2020-07-20 23.0 11.2 7.3 [830 rows x 4 columns]
결측 데이터 처리
결손 값
데이터가 수집되지 않았거나 측정 장치의 고장, 사건 사고 등으로 데이터를 확보할 수 없을 수도 있다.
그러한 값을 결손값이라한다.
결손 값은isna() 함수를 이용하여 찾을 수 있다. 결손 값은 NaN으로 표기된다.
weather_df[weather_df['평균풍속'].isna()] 일시 평균기온 최대풍속 평균풍속 559 2012-02-11 -0.7 NaN NaN 560 2012-02-12 0.4 NaN NaN 561 2012-02-13 4.0 NaN NaN 1694 2015-03-22 10.1 11.6 NaN 1704 2015-04-01 7.3 12.1 NaN 3182 2019-04-18 15.7 11.7 NaN이러한 결손값은 fillna() 함수를 이용하여 채워줄 수 있다. 채울 값을 인자로 전달하고 inplace를 True로 설정하면 원본을 덮어쓴다는 뜻이다.
결손 값을 채운 뒤 위에서 살펴봤던 559번째의 데이터를 출력해보니 0으로 채워진 것을 볼 수 있다.
>>> weather_df.fillna(0, inplace=True) >>> weather_df.loc[559] 일시 2012-02-11 평균기온 -0.7 최대풍속 0.0 평균풍속 0.0 Name: 559, dtype: object
데이터 조작
데이터 구조 변경
import pandas as pd df_1 = pd.DataFrame({'item' : ['ring0', 'ring0', 'ring1', 'ring1'], 'type' : ['Gold', 'Silver', 'Gold', 'Bronze'], 'price': [20000, 10000, 50000, 30000]}) df_2 = df_1.pivot(index='item', columns='type', values='price') print(df_1) print() # 단순 줄바꿈 print(df_2)item type price
0 ring0 Gold 20000
1 ring0 Silver 10000
2 ring1 Gold 50000
3 ring1 Bronze 30000
type Bronze Gold Silver
item
ring0 NaN 20000.0 10000.0
ring1 30000.0 50000.0 NaNdf_1을 보면 동일한 상품이 서로 다른 행에 중복하여 두고 있어 자료를 찾기 쉽지 않다.
인덱스를 item으로 하고 type을 열의 레이블로 하여 데이터 프레임을 변경하였다.
pivot() 함수를 사용하였는데 index, columns, values를 각각 지정해주면 된다.
데이터 프레임 합치기
>>> import pandas as pd >>> df_1 = pd.DataFrame( {'A' : ['a10', 'a11', 'a12'], 'B' : ['b10', 'b11', 'b12'], 'C' : ['c10', 'c11', 'c12']} , index = ['가', '나', '다'] ) >>> df_2 = pd.DataFrame( {'B' : ['b23', 'b24', 'b25'], 'C' : ['c23', 'c24', 'c25'], 'D' : ['d23', 'd24', 'd25']} , index = ['다', '라', '마'] ) >>> df_1 A B C 가 a10 b10 c10 나 a11 b11 c11 다 a12 b12 c12 >>> df_2 B C D 다 b23 c23 d23 라 b24 c24 d24 마 b25 c25 d25
contcat()
df_1과 df_2를 concat을 이용하여 합쳐보자.

axis : 0이면 데이블의 행을 늘려서 붙여나감, 1이면 열을 늘려서 붙여 나감
join : outer 이면 합집합, inner 이면 교집합으로 생성
merge()
데이터베이스는 Join 연산을 지원하는데 이 연산은 서로 다른 2개의 테이블을 결합하는 연산이다.
이 join연산과 같은 방식의 데이터 병합을 지원하는 판다스 함수가 merge()이다.

how : outer이면 합집합, inner이면 교집합,
right 이면 outer 조인의 결과에서 왼쪽 프레임에 존재하는 키를 가진 것만 뽑아낸다.
left 이면 outer 조인의 결과에서 오른쪽 프레임에 존재하는 키를 가진 것만 뽑아낸다.
on : 조인 연산을 수행하기 위해 사용할 레이블
데이터 정렬
sort_values() 함수를 이용하여 쉽게 정렬할 수 있다. 인자로는 정렬시킬 열의 이름을 전달하면 된다.
ascending=True : 오름차순
ascending=False : 내림차순
>>> import pandas as pd >>> countries_df = pd.read_csv('../data/countries.csv', index_col=0) >>> sorted = countries_df.sort_values('population', ascending=False) >>> sorted country area capital population CN China 9596960 Beijing 1439323688 US USA 9629091 Washington 331002825 RU Russia 17100000 Moscow 146748600 JP Japan 377835 Tokyo 125960000 KR Korea 98480 Seoul 51780579
지금까지 배운 것들로
울릉도의 바람 세기를 분석
weather.csv의 데이터를 분석하여 월별 바람세기의 평균을 그래프로 나타내었다.
import pandas as pd import matplotlib.pyplot as plt weather = pd.read_csv('../data/weather.csv', encoding='cp949') monthly = [None for x in range(12)] monthly_wind = [0 for y in range(12)] weather['month'] = pd.DatetimeIndex(weather['일시']).month for i in range(12): monthly[i] = weather[weather['month'] == i + 1] monthly_wind[i] = monthly[i]['평균풍속'].mean() plt.xlabel('months') plt.ylabel('wind speed') plt.plot(monthly_wind, 'red') plt.show()
자동차 회사 연비 분석
자동차 회사 P와 Q가 있다.
P 회사의 차종별 마력, 총중량, 연비
A B C D E F G 마력 130 250 190 300 210 220 170 총중량 1900 2600 2200 2900 2400 2300 2200 연비 16.3 10.2 11.1 7.1 12.1 13.2 14.2 Q 회사의 차종별 마력, 총중량, 연비
A B C D 마력 120 220 120 200 총중량 1900 2100 1500 2900 연비 18.3 19.2 21.1 17.3 자동차 회사 P와 Q 중 어떤 회사의 차량이 평균적으로 연비가 높은지 분석해보자.
import pandas as pd # 데이터 프레임 생성 df_Q = pd.DataFrame({ 'name': ['A', 'B', 'C', 'D'], 'horse power': [120, 220, 120, 200], 'weight': [1.9, 2.1, 1.5, 2.9], 'efficiency': [18.3, 19.2, 21.1, 17.3] }) df_P = pd.DataFrame({ 'name': ['A', 'B', 'C', 'D', 'E', 'F', 'G'], 'horse power': [130, 250, 190, 300, 210, 220, 170], 'weight': [1.9, 2.6, 2.2, 2.9, 2.4, 2.3, 2.2], 'efficiency': [16.3, 10.2, 11.1, 7.1, 12.1, 13.2, 14.2] }) # 인덱스를 name으로 만들고 df_P와 df_Q를 합침 df_Q.set_index('name', inplace=True) df_P.set_index('name', inplace=True) df_concat = pd.concat([df_P, df_Q]) # 각 차량의 제조사를 알 수 있게 'com' 열을 만듦 df_P['com'] = 'P' df_Q['com'] = 'Q' df_concat = pd.concat([df_P, df_Q]) print("------------DataFrame----------") print(df_concat) # 'com'열을 그루핑하여 회사별로 연비의 평균을 구함 df_concat['hp x mile'] = (df_concat['horse power'] * df_concat['efficiency']) print("------------result----------") print(df_concat.groupby('com').mean()['hp x mile'])------------DataFrame----------
horse power weight efficiency com
name
A 130 1.9 16.3 P
B 250 2.6 10.2 P
C 190 2.2 11.1 P
D 300 2.9 7.1 P
E 210 2.4 12.1 P
F 220 2.3 13.2 P
G 170 2.2 14.2 P
A 120 1.9 18.3 Q
B 220 2.1 19.2 Q
C 120 1.5 21.1 Q
D 200 2.9 17.3 Q
------------result----------
com
P 2395.285714
Q 3103.000000
Name: hp x mile, dtype: float64데이터 분석 너무너무 재밌는 것 같다.
이번 장은 내용이 좀 많았는데 시간 가는 줄 모르고 블로그 작성했다.
728x90'Deep Learning > 인공지능 입문 코딩' 카테고리의 다른 글
[CHAPTER 14] Machine Learning (0) 2021.06.10 [CHAPTER 13] OpenCV (0) 2021.06.06 [CHAPTER 11] 데이터 시각화 | matplotlib (0) 2021.06.02 [CHAPTER 10]넘파이(numpy) (0) 2021.05.30 [CHAPTER 9] 텍스트 처리 (0) 2021.05.29