[Python으로 데이터 다루기 II - Pandas]4강:Pandas의 Dataframe

4 minute read

Pandas로 2차원 데이터 다루기 - dataframe

dataframe?

  • 2-D labeled table
  • key와 value가 있는 labeled된 자료구조
  • 인덱스를 지정할 수도 있음. 데이터를 참조하는 데 쓰임 딕셔너리를 사용하여 데이터프레임을 만들 수 있다.
    Series에서는 리스트로 먼저 시작했지만, 데이터프레임의 경우 리스트만 가지고는 2차원 구조를 만들기 버겁다는 특징이 있다.
    표(테이블)이라는 데이터 자체가 가로와 세로를 가져야 하는데, 리스트보다는 딕셔너리가 2차원 구조를 표현하기에 적합하다.
d = {"height":[1, 2, 3, 4], "weight":[30, 40, 50, 60]}

df = pd.DataFrame(d)

df
# 	height	weight
# 0	    1	    30
# 1	    2	    40
# 2	    3	    50
# 3	    4	    60

행이 어떤 특정 데이터 하나를 의미하고, 각 데이터는 여러 column을 가지는 형태를 볼 수 있다.
예를 들어 인덱스 0의 데이터는 height가 1이고 weight가 30인 데이터이다.
데이터프레임의 경우 numpy의 array와 다르게 숫자만 받는 게 아니라 문자, 날짜, 객체 등 여러 타입을 다뤄줄 수 있다. 따라서 height, weight 열에 대해 어떤 자료형이 담겼는지 확인해줄 필요가 있다.
numpy에서는 동일한 데이터를 담았기 때문에 numpy.array.dtype와 같이 적어줬었다.
pandas의 경우 여러 열이 존재하기 때문에, 각 열에 따라 데이터타입이 다를 수 있다.
df.dtypes

# dtype 확인
df.dtypes
# height    int64
# weight    int64
# dtype: object



From CSV to dataframe

pandas는 csv(데이터) -> dataframe으로 바꿀 수 있는 함수를 지원한다.

  • Comma Separated Value를 Data Frame으로 생성해줄 수 있다.
  • .read_csv()를 이용 https://www.kaggle.com/imdevskp/corona-virus-report#
    위 링크에서 COVID-19데이터셋 다운로드!
# 동일 경로에 country_wise_latest.csv가 존재하면:
covid = pd.read_csv("./archive/country_wise_latest.csv") # csv 파일이 있는 경로

covid



Pandas 활용 1. 일부분만 관찰하기

head(n) : 처음 n개의 데이터 참조

# 위에서부터 5개를 관찰하는 방법(함수)
covid.head(5)

tail(n) : 마지막 n개의 데이터 참조

# 아래에서부터 5개를 관찰하는 방법(함수)
covid.tail(5)



Pandas 활용 2. 데이터 접근하기

  • df['column name'] or df.column_name
covid['Active'] # 띄어쓰기 포함된 Key를 찾을 수 있음
covid.Active # 띄어쓰기 포함된 Key를 찾을 수 없음

주의! : csv에서 column의 name은 띄어쓰기가 들어있다. 따라서 띄어쓰기가 들어있는 열을 접근하기 위해서는 df.column_name이 아닌 df['column name']을 써야 한다.

Honey Tip! Dataframe의 각 column은 “Series”다!

type(covid['Confirmed'])
# pandas.core.series.Series

csv의 열 중 하나인 ‘Confirmed’를 키를 갖는 열의 타입을 한번 살펴보니 Series라고 나온다!
각 열이 Series이다. 즉 데이터프레임은 사실 Series의 별렬적인 모음이다. 레코드 단위로 묶은 것이다.
Series를 얻었다는 것은, 인덱싱, 슬라이싱 등의 액션을 취해줄 수 있다는 것이다.

covid['Confirmed'][0] # 인덱스로 값 접근 
# 36263

covid['Confirmed'][1:5] # 슬라이싱
# 1     4880
# 2    27973
# 3      907
# 4      950
# Name: Confirmed, dtype: int64



Pandas 활용 3. “조건”을 이용해서 데이터 접근하기

# 신규확진자가 100명이 넘는 나라를 찾아보자!
# csv에서 New cases가 신규확진자이다.
covid[covid['New cases'] > 100]
# covid['New cases'] > 100는 100이 넘는 값에 대해 True/False를 반환한다. 이 결과를 covid의 key로 넣으면 key에 대한 값들만 출력해준다.
covid[covid['New cases'] > 100].head(5)
# WHO 지역(WHO Region)이 동남아시아인 나라 찾기

covid['WHO Region'].unique() # 해당 열에 존재하는 유니크 값 찾기
# array(['Eastern Mediterranean', 'Europe', 'Africa', 'Americas',
#        'Western Pacific', 'South-East Asia'], dtype=object)

covid[covid['WHO Region'] == 'South-East Asia']



Pandas 활용 4. 행을 기준으로 데이터 접근하기

# 예시 데이터 - 도서관 정보

books_dict = {"Available":[True, True, False], "Location":[102, 215, 323], "Genre":["Programming", "Physics", "Math"]}

books_dict
# {'Available': [True, True, False],
#  'Location': [102, 215, 323],
#  'Genre': ['Programming', 'Physics', 'Math']}

books_df = pd.DataFrame(books_dict, index=['버그란 무엇인가', '두근두근 물리학', '미분해줘 홈즈'])

books_df
# 	            Available	Location	Genre
# 버그란 무엇인가	True	    102	        Programming
# 두근두근 물리학	True	    215	        Physics
# 미분해줘 홈즈	   False	   323	       Math



인덱스를 이용해서 가저오기 : .loc[row, col]

행과 열의 값을 특정해서 가져올 수 있다.

books_df.loc["버그란 무엇인가"]
# Available           True
# Location             102
# Genre        Programming
# Name: 버그란 무엇인가, dtype: object

type(books_df.loc["버그란 무엇인가"])
# pandas.core.series.Series
# "미분해줘 홈즈"책이 대출 가능한지?
books_df.loc["미분해줘 홈즈"]['Available'] # False
books_df.loc["미분해줘 홈즈", 'Available'] # False



숫자 인덱스를 이용해서 가져오기 : `.iloc[rowidx, colidx]

문자 인덱스가 아닌 숫자 인덱스를 이용해 값을 가져올 수 있다. 순수하게 위치의 값으로 값을 가져올 수 있다.

# 인덱스 0행의 인덱스 1열 가지고 오기
books_df.iloc[0, 1] # 102

# 인덱스 1행의 인덱스 0~1열 가지고오기
books_df.iloc[1, 0:2]




Pandas 활용 5. groupby

  • Split : 특정한 “기준”을 바탕으로 DataFrame을 분할
  • Apply : 통계함수 - sum(), mean(), median(), - 을 적용해서 각 데이터를 압축
  • Combine : Apply된 결과를 바탕으로 새로운 Series를 생성(group_key : applied_value) .groupby()
covid.head(5)

# WHO Region 별 확진자수

# 1. covid에서 확진자 수 column만 추출한다
# 2. 이를 covid의 WHO Region을 기준으로 groupby한다.
covid_by_region = covid['Confirmed'].groupby(by=covid["WHO Region"])

covid_by_region
# <pandas.core.groupby.generic.SeriesGroupBy object at 0x118a125e0>

결과가 표가 아니라 저런 객체가 나오는 이유는, 지금 groupby의 세가지 프로세스 중에 Split만 수행했기 때문이다.
Split만 사용하면 데이터가 분산되어있기만 하지 유의미한 정보를 출력할 수는 없다.
Apply를 진행하면, 즉 통계함수를 Split된 객체에 적용하면 Combine도 같이 된다.

covid_by_region.sum()
# WHO Region
# Africa                    723207
# Americas                 8839286
# Eastern Mediterranean    1490744
# Europe                   3299523
# South-East Asia          1835297
# Western Pacific           292428
# Name: Confirmed, dtype: int64

여기서잠깐! 표본의 수가 많아서 확진자 수가 많게 집계되어 보이는 것일 수도 있지 않은가?

# 국가당 감염자 수
covid_by_region.mean() # sum() / 국가 수
# WHO Region
# Africa                    15066.812500
# Americas                 252551.028571
# Eastern Mediterranean     67761.090909
# Europe                    58920.053571
# South-East Asia          183529.700000
# Western Pacific           18276.750000
# Name: Confirmed, dtype: float64

우려했던 바와 같이, 유럽같은 경우 표본의 수가 많아서 확진자 수가 많이 집계된 경우였다.
South-East Asia의 경우 국가당 확진자 수가 많은 것임을 알 수 있다.
이런 식으로 새로운 인사이트들을 뽑아낼 수 있다.



1. covid 데이터에서 100 case 대비 사망률(Deaths / 100 Cases)이 가장 높은 국가는?

import pandas as pd
covid = pd.read_csv("./archive/country_wise_latest.csv")

covid[covid['Deaths / 100 Cases'] == covid['Deaths / 100 Cases'].max()]['Country/Region']

2. covid 데이터에서 신규 확진자가 없는 나라 중 WHO Region이 ‘Europe’를 모두 출력하면?

Hint : 한 줄에 동시에 두가지 조건을 Apply하는 경우 Warning이 발생할 수 있습니다.

covid_no_cases = covid['New cases']==0
covid_europe = covid['WHO Region']=='Europe'
answer = covid[covid_no_cases & covid_europe]
answer

3. 다음 데이터를 이용해 각 Region별로 아보카도가 가장 비싼 평균가격(AveragePrice)을 출력하면?

avocado = pd.read_csv("./archive/avocado.csv")
exp = avocado.groupby(avocado['region'])
exp.max()