import pandas as pd
import numpy as np
08wk-2: Pandas – groupby
, 데이터프레임의 결합
pandas
1. 강의영상
2. Imports
3. groupby
A. DataFrameGroupBy
-
groupby
+ agg
의 복습
= pd.DataFrame({'department':['A','A','B','B'], 'gender':['male','female','male','female'],'count':[1,2,3,1]})
df df
department | gender | count | |
---|---|---|---|
0 | A | male | 1 |
1 | A | female | 2 |
2 | B | male | 3 |
3 | B | female | 1 |
'department').agg({'count':'sum'}) df.groupby(
count | |
---|---|
department | |
A | 3 |
B | 4 |
-
의문: 위의 코드에서 df.groupby('department')
는 어떤 object일까?
= df.groupby('department')
g g
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x7f3d9461c9d0>
set(dir(g)) & {'__iter__'} # g는 반복문을 돌리기 유리하게 설계되어 있음
{'__iter__'}
list(g) # for문의 반복인자는 ('A',sub-dataframe)와 같은 형식의 tuple임
[('A',
department gender count
0 A male 1
1 A female 2),
('B',
department gender count
2 B male 3
3 B female 1)]
오브젝트 g
는
- sub-dataframe 이 모여있는 묶음체이다.
- 반복문을 돌리기에 용이하도록 고안되어있다. (이때 각 반복인자는
(묵음기준,sub-dataframe)
의 튜플로 이루어져 있음)
-
제가 이해하는 방식
= {k:df for k,df in g}
dct dct
{'A': department gender count
0 A male 1
1 A female 2,
'B': department gender count
2 B male 3
3 B female 1}
'A'])
display(dct['B']) display(dct[
department | gender | count | |
---|---|---|---|
0 | A | male | 1 |
1 | A | female | 2 |
department | gender | count | |
---|---|---|---|
2 | B | male | 3 |
3 | B | female | 1 |
B. g
를 이용하는 방법
# 예시1
: g
를 이용하여 원래의 df를 복원하라.
= pd.DataFrame({'department':['A','A','B','B'], 'gender':['male','female','male','female'],'count':[1,2,3,1]})
df = df.groupby('department') g
(풀이)
for _,df in g]) pd.concat([df
department | gender | count | |
---|---|---|---|
0 | A | male | 1 |
1 | A | female | 2 |
2 | B | male | 3 |
3 | B | female | 1 |
#
# 예시2
: g
를 이용하여 아래와 동일한 기능을 하는 코드를 작성하라. (agg 함수 사용금지)
= pd.DataFrame({'department':['A','A','B','B'], 'gender':['male','female','male','female'],'count':[1,2,3,1]})
df 'department').agg({'count':'sum'}) df.groupby(
count | |
---|---|
department | |
A | 3 |
B | 4 |
(풀이)
= df.groupby('department')
g g
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x7f3d9461fdc0>
'count'].sum() for k,df in g})) pd.DataFrame(pd.Series({k:df[
0 | |
---|---|
A | 3 |
B | 4 |
#
# 예시3
: 아래는 데이터프레임이 있다고 치자. 이 데이터프레임을 class
를 기준으로 그룹핑하여 sub-dataframe을 만들고 score가 높은 순서로 정렬하는 코드를 작성하라.
= pd.DataFrame({'class':['A']*5+['B']*5, 'id':[0,1,2,3,4]*2, 'score':[60,20,40,60,90,20,30,90,95,95]})
df df
class | id | score | |
---|---|---|---|
0 | A | 0 | 60 |
1 | A | 1 | 20 |
2 | A | 2 | 40 |
3 | A | 3 | 60 |
4 | A | 4 | 90 |
5 | B | 0 | 20 |
6 | B | 1 | 30 |
7 | B | 2 | 90 |
8 | B | 3 | 95 |
9 | B | 4 | 95 |
(풀이)
'score',ascending=False) for k,df in df.groupby('class')]) pd.concat([df.sort_values(
class | id | score | |
---|---|---|---|
4 | A | 4 | 90 |
0 | A | 0 | 60 |
3 | A | 3 | 60 |
2 | A | 2 | 40 |
1 | A | 1 | 20 |
8 | B | 3 | 95 |
9 | B | 4 | 95 |
7 | B | 2 | 90 |
6 | B | 1 | 30 |
5 | B | 0 | 20 |
#
4. concat
pass
5. merge
A. 가장 빈번하게 사용하는 상황
# 예시1
– big
dataframe에 groupby
+agg
를 사용하여 small
dataframe이 생긴경우
= pd.DataFrame({'department':['A','A','B','B'], 'gender':['male','female','male','female'],'count':[1,2,3,1]})
big = pd.DataFrame({'department':['A','B'], 'count_sum':[3,4]}) small
"big",big)
display("small",small) display(
'big'
department | gender | count | |
---|---|---|---|
0 | A | male | 1 |
1 | A | female | 2 |
2 | B | male | 3 |
3 | B | female | 1 |
'small'
department | count_sum | |
---|---|---|
0 | A | 3 |
1 | B | 4 |
-
정보를 종합하기 위해서는 아래와 같이 하면 된다.
pd.merge(big,small)
big.merge(small)#---#
pd.merge(small,big) small.merge(big)
department | count_sum | gender | count | |
---|---|---|---|---|
0 | A | 3 | male | 1 |
1 | A | 3 | female | 2 |
2 | B | 4 | male | 3 |
3 | B | 4 | female | 1 |
-
merge에 대한 약간의 개념
- 상황: 두 데이터프레임은 특정한 IndexLabel에 대하여 서로 다른 정보를 각각 정리한 상황
- 원리: (1) 연결고리파악: 두 데이터프레임에서 공통인 열(IndexLabel)을 찾는다. (2) 병합: 연결고리를 기준으로 데이터의 정보를 병합한다.
이 예시의 경우
- IndexLabel = 연결고리 = 공통의열 =
department
- 서로다른정보들: 이 예제에서 big은
department
에 대한gender
와count
를 정리하고 있음. 그리고 small은department
에 대한count_sum
을 정리하고 있음. 이는 서로 다른 정보임.
배울게 좀 더 남음: 사실 아래는 같은 코드이다.
pd.merge(big,small)='department') pd.merge(big,small, on
department | gender | count | count_sum | |
---|---|---|---|---|
0 | A | male | 1 | 3 |
1 | A | female | 2 | 3 |
2 | B | male | 3 | 4 |
3 | B | female | 1 | 4 |
#
B. 여러가지 파라메터
# 예시1
– on
= pd.DataFrame({'department':['A','A','B','B'], 'gender':['male','female','male','female'],'count':[1,2,3,1]})
big = big.groupby('department').agg({'count':'sum'}).reset_index()
small "big",big)
display("small",small) display(
'big'
department | gender | count | |
---|---|---|---|
0 | A | male | 1 |
1 | A | female | 2 |
2 | B | male | 3 |
3 | B | female | 1 |
'small'
department | count | |
---|---|---|
0 | A | 3 |
1 | B | 4 |
-
잘못된 코드
pd.merge(big,small)
department | gender | count |
---|
-
올바른 코드
='department') pd.merge(big,small,on
department | gender | count_x | count_y | |
---|---|---|---|---|
0 | A | male | 1 | 3 |
1 | A | female | 2 | 3 |
2 | B | male | 3 | 4 |
3 | B | female | 1 | 4 |
*
더(?) 올바른 코드 – 좀 더 제 스타일의 코드
'count':'count_sum'},axis=1)) pd.merge(big,small.rename({
department | gender | count | count_sum | |
---|---|---|---|---|
0 | A | male | 1 | 3 |
1 | A | female | 2 | 3 |
2 | B | male | 3 | 4 |
3 | B | female | 1 | 4 |
배울게 좀 더 남음: 사실 아래는 같은 코드이다.
='department')
pd.merge(big,small,on='department', right_on='department') pd.merge(big,small,left_on
department | gender | count_x | count_y | |
---|---|---|---|---|
0 | A | male | 1 | 3 |
1 | A | female | 2 | 3 |
2 | B | male | 3 | 4 |
3 | B | female | 1 | 4 |
#
# 예시2
– left_on, right_on
= pd.DataFrame({'department':['A','A','B','B'], 'gender':['male','female','male','female'],'count':[1,2,3,1]})
big = pd.DataFrame({'dept':['A','B'], 'count':[3,4]})
small "big",big)
display("small",small) display(
'big'
department | gender | count | |
---|---|---|---|
0 | A | male | 1 |
1 | A | female | 2 |
2 | B | male | 3 |
3 | B | female | 1 |
'small'
dept | count | |
---|---|---|
0 | A | 3 |
1 | B | 4 |
- 공통의 열이 오히려 ‘count’ 이고 서로 다른 정보들은 ‘gender’,‘department’,‘dept’ 이다.
-
잘못된 코드
pd.merge(big,small)
department | gender | count | dept | |
---|---|---|---|---|
0 | B | male | 3 | A |
-
올바른 코드
='department',right_on='dept') pd.merge(big,small,left_on
department | gender | count_x | dept | count_y | |
---|---|---|---|---|---|
0 | A | male | 1 | A | 3 |
1 | A | female | 2 | A | 3 |
2 | B | male | 3 | B | 4 |
3 | B | female | 1 | B | 4 |
*
좀 더 제 스타일의 코드
'department','count_sum'],axis=1)) pd.merge(big,small.set_axis([
department | gender | count | count_sum | |
---|---|---|---|---|
0 | A | male | 1 | 3 |
1 | A | female | 2 | 3 |
2 | B | male | 3 | 4 |
3 | B | female | 1 | 4 |
#
# 예제3
: how
= pd.DataFrame({
df1 'dept':['통계','수학','과학','IAB'],
'count':[20,30,25,50]
})= pd.DataFrame({
df2 'dept':['통계','수학','과학','신설학과'],
'desc':['통계학과는...','수학과는...','과학학과는...','이 학과는 내년에 신설될 예정이고...']
})"df1",df1)
display("df2",df2) display(
'df1'
dept | count | |
---|---|---|
0 | 통계 | 20 |
1 | 수학 | 30 |
2 | 과학 | 25 |
3 | IAB | 50 |
'df2'
dept | desc | |
---|---|---|
0 | 통계 | 통계학과는... |
1 | 수학 | 수학과는... |
2 | 과학 | 과학학과는... |
3 | 신설학과 | 이 학과는 내년에 신설될 예정이고... |
- 공통의열인
dept
와 서로다른 정보인count
,desc
들의 이름이 예쁘게 정리되어 있어on
,left_on
,right_on
와 같은 파라메터를 사용할 필요가 없다.
# IAB, 신설학과는 사라짐 pd.merge(df1,df2)
dept | count | desc | |
---|---|---|---|
0 | 통계 | 20 | 통계학과는... |
1 | 수학 | 30 | 수학과는... |
2 | 과학 | 25 | 과학학과는... |
-
상황: IAB 학과는 df1에만, 신설학과는 df2에만 존재한다. \(\to\) IAB와 신설학과를 처리하는 방식에 따라서 4가지 경우로 나누어진다.
# 경우1: 두 학과 모두 제거 = 두 데이터프레임의 공통만 취함
pd.merge(df1,df2)='inner') pd.merge(df1,df2,how
dept | count | desc | |
---|---|---|---|
0 | 통계 | 20 | 통계학과는... |
1 | 수학 | 30 | 수학과는... |
2 | 과학 | 25 | 과학학과는... |
# 경우2: IAB만 살림 = 왼쪽 데이터프레임에 포함된 모든 학과는 살림
pd.merge(df1,df2)='left') pd.merge(df1,df2,how
dept | count | desc | |
---|---|---|---|
0 | 통계 | 20 | 통계학과는... |
1 | 수학 | 30 | 수학과는... |
2 | 과학 | 25 | 과학학과는... |
3 | IAB | 50 | NaN |
# 경우3: 신설학과만 살람 = 오른쪽 데이터프레임에 포함된 모든학과를 살람
pd.merge(df1,df2)='right') pd.merge(df1,df2,how
dept | count | desc | |
---|---|---|---|
0 | 통계 | 20.0 | 통계학과는... |
1 | 수학 | 30.0 | 수학과는... |
2 | 과학 | 25.0 | 과학학과는... |
3 | 신설학과 | NaN | 이 학과는 내년에 신설될 예정이고... |
# 경우4: 두 학과 모두 살림
pd.merge(df1,df2)='outer') pd.merge(df1,df2,how
dept | count | desc | |
---|---|---|---|
0 | 통계 | 20.0 | 통계학과는... |
1 | 수학 | 30.0 | 수학과는... |
2 | 과학 | 25.0 | 과학학과는... |
3 | IAB | 50.0 | NaN |
4 | 신설학과 | NaN | 이 학과는 내년에 신설될 예정이고... |
6. concat
, merge
를 이용한 데이터 합치기
# 예제
– 전북대학교 통계학과 교과목
주어진 자료가 아래와 같다.
= pd.DataFrame({
df_course2023 'name':['최규빈']*3+['최혜미']*2+['이영미']+['양성준'],
'year':[2023]*7,
'course':['파이썬프로그래밍', '데이터시각화', '기계학습활용','수리통계1', '수리통계2','회귀분석1','통계수학']})
df_course2023
name | year | course | |
---|---|---|---|
0 | 최규빈 | 2023 | 파이썬프로그래밍 |
1 | 최규빈 | 2023 | 데이터시각화 |
2 | 최규빈 | 2023 | 기계학습활용 |
3 | 최혜미 | 2023 | 수리통계1 |
4 | 최혜미 | 2023 | 수리통계2 |
5 | 이영미 | 2023 | 회귀분석1 |
6 | 양성준 | 2023 | 통계수학 |
= pd.DataFrame({
df_course2024 'name':['최규빈','이영미','이영미','양성준','최혜미'],
'year':[2024]*5,
'course':['기계학습활용','수리통계1', '수리통계2','회귀분석1','통계수학']})
df_course2024
name | year | course | |
---|---|---|---|
0 | 최규빈 | 2024 | 기계학습활용 |
1 | 이영미 | 2024 | 수리통계1 |
2 | 이영미 | 2024 | 수리통계2 |
3 | 양성준 | 2024 | 회귀분석1 |
4 | 최혜미 | 2024 | 통계수학 |
= pd.DataFrame({
df_score 'name':['최규빈','최규빈','이영미','이영미','양성준','양성준','최혜미','최혜미'],
'year':[2023,2024]*4,
'score':[1, 1.2, 5,5,5,5,5,5]})
df_score
name | year | score | |
---|---|---|---|
0 | 최규빈 | 2023 | 1.0 |
1 | 최규빈 | 2024 | 1.2 |
2 | 이영미 | 2023 | 5.0 |
3 | 이영미 | 2024 | 5.0 |
4 | 양성준 | 2023 | 5.0 |
5 | 양성준 | 2024 | 5.0 |
6 | 최혜미 | 2023 | 5.0 |
7 | 최혜미 | 2024 | 5.0 |
= pd.DataFrame({'name':['최규빈','이영미','양성준','최혜미'],
df_sex 'sex':['male','female','male','female']})
df_sex
name | sex | |
---|---|---|
0 | 최규빈 | male |
1 | 이영미 | female |
2 | 양성준 | male |
3 | 최혜미 | female |
주어진 정보를 바탕으로, 4개의 데이터 프레임을 결합하라.
(풀이)
\
pd.concat([df_course2023,df_course2024])=['name','year'])\
.merge(df_score, on='name') .merge(df_sex, on
name | year | course | score | sex | |
---|---|---|---|---|---|
0 | 최규빈 | 2023 | 파이썬프로그래밍 | 1.0 | male |
1 | 최규빈 | 2023 | 데이터시각화 | 1.0 | male |
2 | 최규빈 | 2023 | 기계학습활용 | 1.0 | male |
3 | 최규빈 | 2024 | 기계학습활용 | 1.2 | male |
4 | 최혜미 | 2023 | 수리통계1 | 5.0 | female |
5 | 최혜미 | 2023 | 수리통계2 | 5.0 | female |
6 | 최혜미 | 2024 | 통계수학 | 5.0 | female |
7 | 이영미 | 2023 | 회귀분석1 | 5.0 | female |
8 | 이영미 | 2024 | 수리통계1 | 5.0 | female |
9 | 이영미 | 2024 | 수리통계2 | 5.0 | female |
10 | 양성준 | 2023 | 통계수학 | 5.0 | male |
11 | 양성준 | 2024 | 회귀분석1 | 5.0 | male |
#
7. HW
없음