Pandas Iterrows 함수 활용
강의 홍보
- 취준생을 위한 강의를 제작하였습니다.
- 본 블로그를 통해서 강의를 수강하신 분은 게시글 제목과 링크를 수강하여 인프런 메시지를 통해 보내주시기를 바랍니다.
스타벅스 아이스 아메리카노를 선물
로 보내드리겠습니다.
- [비전공자 대환영] 제로베이스도 쉽게 입문하는 파이썬 데이터 분석 - 캐글입문기
I. Iterrows의 개념
데이터 전처리를 진행할 때, 데이터프레임에서 행에 반복적으로 접근을 하면서 값을 추출하거나 또는 그 값을 조작하는 일이 발생한다. 예를 들면, 특정 컬럼 A의 값에서 대문자 A를 찾아내 소문자 b로 변경한다고 가정해보자. 이런 경우에는 언제나 For-loop를 통한 반복문 코드 작성을 만들어야 한다.
이럴 때 보다 효율적으로 접근하는 방법 중 하나가 iterrows()
를 사용하는 경우이다.
import pandas as pd
import io
import requests
import pprint
url = 'https://raw.githubusercontent.com/chloevan/datasets/master/sports/baseball_stats.csv'
url=requests.get(url).content
baseball_stats = pd.read_csv(io.StringIO(url.decode('utf-8')))
pprint.pprint(baseball_stats.head())
Team League Year RS RA W OBP SLG BA Playoffs RankSeason \
0 ARI NL 2012 734 688 81 0.33 0.42 0.26 0 NaN
1 ATL NL 2012 700 600 94 0.32 0.39 0.25 1 4.0
2 BAL AL 2012 712 705 93 0.31 0.42 0.25 1 5.0
3 BOS AL 2012 734 806 69 0.32 0.41 0.26 0 NaN
4 CHC NL 2012 613 759 61 0.30 0.38 0.24 0 NaN
RankPlayoffs G OOBP OSLG
0 NaN 162 0.32 0.41
1 5.0 162 0.31 0.38
2 4.0 162 0.32 0.40
3 NaN 162 0.33 0.43
4 NaN 162 0.34 0.42
II. 조건부 행 추출
드디어 Python 데이터 분석가로 보스턴 레드박스(BOS)
야구팀에 취직을 했다고 가정을 해보자. 단장이 2008 ~ 2010년까지의 득점과 실점의 차이를 보고 싶다고 요청을 해왔다. 이럴 때 어떻게 해야 할까?
bos_df = baseball_stats[baseball_stats.Team == "BOS"].reset_index(drop = True)
pprint.pprint(bos_df.head())
Team League Year RS RA W OBP SLG BA Playoffs RankSeason \
0 BOS AL 2012 734 806 69 0.32 0.41 0.26 0 NaN
1 BOS AL 2011 875 737 90 0.35 0.46 0.28 0 NaN
2 BOS AL 2010 818 744 89 0.34 0.45 0.27 0 NaN
3 BOS AL 2009 872 736 95 0.35 0.45 0.27 1 3.0
4 BOS AL 2008 845 694 95 0.36 0.45 0.28 1 3.0
RankPlayoffs G OOBP OSLG
0 NaN 162 0.33 0.43
1 NaN 162 0.32 0.39
2 NaN 162 0.33 0.40
3 4.0 162 0.34 0.42
4 3.0 162 0.32 0.39
이 때, 중요한 것 중의 하나는 .reset_index(drop = True)
활용법인데, 기존의 행 인덱스를 제거하고 0부터 다시 시작하는 것이 특징이다. 위 표에서 보는 것처럼 Team-BOS
데이터만 추출 된 것을 확인할 수 있다.
이제는 Year
컬럼에서 2008~2010년 데이터만 추출한다.
bos_year_df = bos_df[bos_df["Year"].isin([2008, 2009, 2010])].reset_index(drop = True)
pprint.pprint(bos_year_df.head())
Team League Year RS RA W OBP SLG BA Playoffs RankSeason \
0 BOS AL 2010 818 744 89 0.34 0.45 0.27 0 NaN
1 BOS AL 2009 872 736 95 0.35 0.45 0.27 1 3.0
2 BOS AL 2008 845 694 95 0.36 0.45 0.28 1 3.0
RankPlayoffs G OOBP OSLG
0 NaN 162 0.33 0.40
1 4.0 162 0.34 0.42
2 3.0 162 0.32 0.39
이번에 소개하는 함수는 .isin()
인데, 연구자가 원하는 값만 알면 쉽게 추출할 수 있다는 장점이 있다. R
을 사용하는 유저라면 %in%
함수를 기억할 것인데, 이와 매우 유사하다.
III. Data Frame과 For-loop의 실체
Python DataFrame과 For-loop가 만나면 어떻게 작동을 할까? iterrows() 함수를 활용하여 실체를 한번 들여다 보자. 먼저 각 행을 각각 추출해본다.
for i,row in bos_year_df.iterrows():
print(i)
print(row)
print(type(row))
0
Team BOS
League AL
Year 2010
RS 818
RA 744
W 89
OBP 0.34
SLG 0.45
BA 0.27
Playoffs 0
RankSeason NaN
RankPlayoffs NaN
G 162
OOBP 0.33
OSLG 0.4
Name: 0, dtype: object
<class 'pandas.core.series.Series'>
1
Team BOS
League AL
Year 2009
RS 872
RA 736
W 95
OBP 0.35
SLG 0.45
BA 0.27
Playoffs 1
RankSeason 3
RankPlayoffs 4
G 162
OOBP 0.34
OSLG 0.42
Name: 1, dtype: object
<class 'pandas.core.series.Series'>
2
Team BOS
League AL
Year 2008
RS 845
RA 694
W 95
OBP 0.36
SLG 0.45
BA 0.28
Playoffs 1
RankSeason 3
RankPlayoffs 3
G 162
OOBP 0.32
OSLG 0.39
Name: 2, dtype: object
<class 'pandas.core.series.Series'>
DataFrame이 For-loop와 만나게 되면 각 loop에서 row
의 Return
Pandas Series 형태인 것을 확인할 수 있다. For-loop 안에서 데이터 처리를 할 때, Pandas Series 형태인 것을 감안하고 접근해야 한다는 뜻이다.
for row_tuple in bos_year_df.iterrows():
print(row_tuple)
print(type(row_tuple))
(0, Team BOS
League AL
Year 2010
RS 818
RA 744
W 89
OBP 0.34
SLG 0.45
BA 0.27
Playoffs 0
RankSeason NaN
RankPlayoffs NaN
G 162
OOBP 0.33
OSLG 0.4
Name: 0, dtype: object)
<class 'tuple'>
(1, Team BOS
League AL
Year 2009
RS 872
RA 736
W 95
OBP 0.35
SLG 0.45
BA 0.27
Playoffs 1
RankSeason 3
RankPlayoffs 4
G 162
OOBP 0.34
OSLG 0.42
Name: 1, dtype: object)
<class 'tuple'>
(2, Team BOS
League AL
Year 2008
RS 845
RA 694
W 95
OBP 0.36
SLG 0.45
BA 0.28
Playoffs 1
RankSeason 3
RankPlayoffs 3
G 162
OOBP 0.32
OSLG 0.39
Name: 2, dtype: object)
<class 'tuple'>
이번에는 Tuple 형태로 데이터가 Return 했다. DataFrame와 For-loop가 만나면 이렇게 다양한 객체로 다시 Return하는 것을 보았다. Tuple로 결과값을 받을지, 아니면 Series 형태로 받을지는 미리 알고 써야 데이터 처리시의 에러에 잘 대처할 수 있다.
이번에는 득점과 실점을 계산한 후 기존 데이터에 다시 넣는 것을 해본다.
IV. 득점-실점 계산
# 함수 정의
def calc_diff(runs_scored, runs_allowed): # runs_scored: 득점 / runs_allowed: 실점
run_diff = runs_scored - runs_allowed
return run_diff
run_diffs = []
for i,row in bos_year_df.iterrows():
runs_scored = row['RS']
runs_allowed = row['RA']
run_diff = calc_diff(runs_scored, runs_allowed)
run_diffs.append(run_diff)
bos_year_df["RD"] = run_diffs
pprint.pprint(bos_year_df.head())
Team League Year RS RA W OBP SLG BA Playoffs RankSeason \
0 BOS AL 2010 818 744 89 0.34 0.45 0.27 0 NaN
1 BOS AL 2009 872 736 95 0.35 0.45 0.27 1 3.0
2 BOS AL 2008 845 694 95 0.36 0.45 0.28 1 3.0
RankPlayoffs G OOBP OSLG RD
0 NaN 162 0.33 0.40 74
1 4.0 162 0.34 0.42 136
2 3.0 162 0.32 0.39 151
새로운 컬럼 RD
가 나타난 것을 확인할 수 있을 것이다.
오늘 배운 것은 iterrows()
을 활용한 데이터 가공(Transformation)을 배웠다. 다음 시간에는 itertuples()
활용법에 대해 배우도록 한다.
V. Reference
pandas.DataFrame.iterrows¶. (n.d.). Retrieved March 20, 2020, from https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.iterrows.html?highlight=iterrows
End of Document