Py) 기초 - Pandas(GroupBy)

Py) 기초 - Pandas(GroupBy)

파이썬 기반 데이터분석을 위하여 .groupby() 메서드를 활용한 Pandas 객체의 요약을 알아본다.


※ 본 내용에서 사용하는 production_monthly_1990.csv 파일은 별도로 다운로드 받아야 한다.
production_monthly_1990.csv 다운받기 [클릭]

개요

Pandas 객체의 특정 변수를 요약하고자 하는 경우 .sum()이나 .mean() 같은 메서드로 여러 요약 수치를 산출한다. 여기서 더 나아가 다른 변수를 기준으로 이런 요약 수치를 산출하는 작업이 필요할 수 있다. 예를 들어 월별 총 매출, 사용자별 구매상품 종류수 그리고 일별 최저기온 같은 수치가 있을 수 있다. 이러한 수치를 산출하고자 할 때는 월별로 데이터를 별도로 필터링할 수 있지만 이런 작업을 할 경우 중복되는 코드가 많아지거나 반복문을 써야하는 불편함이 있을 수 있다. 이 불편함을 해소해주는 메서드 중 하나가 .groupby() 메서드이다. 이제 groupby() 메서드에 대해 알아보도록 하자.

실습

실습을 위해 데이터를 준비하자.

1
2
df = pd.read_csv("production_monthly_1990.csv")
df.head(2)
year month volumn
0 1990 1 1199.87
1 1990 2 1214.54

만약 .groupby() 메서드를 사용하지 않는다면 다음과 같이 개별 코드를 작성하거나 반복문을 사용해서 처리해야 하니 참고하도록 하자.

1
2
3
4
5
6
7
8
9
10
11
12
13
[df.loc[df["year"] == 1990, "volumn"].mean(), 
df.loc[df["year"] == 1991, "volumn"].mean(),
df.loc[df["year"] == 1992, "volumn"].mean(),
df.loc[df["year"] == 1993, "volumn"].mean()]
## [1265.9566666666667, 1316.8275, 1231.8875, 1255.1999999999998]


ls_mean = []
for n in range(1990, 1994):
ls_mean = ls_mean + [df.loc[df["year"] == n, "volumn"].mean()]

ls_mean
## [1265.9566666666667, 1316.8275, 1231.8875, 1255.1999999999998]

기본형

.groupby() 메서드는 메서드 내부에 데이터프레임의 특정 변수를 기준 변수로 해서 해당 변수를 기준으로 다른 변수의 요약 연산을 실시할 수 있도록 지원하는 메서드이다.

.groupby() 메서드 개요

기준 변수의 경우 그 개수가 하나일 경우 단순 문자열로 입력하면 되나, 두 개 이상인 경우 변수명을 리스트로 감싼다. 그리고 요약 연산의 대상이 되는 변수는 메서드 뒤에 대괄호를 사용하여 명시하며 기준 변수와 같이 두 개 이상의 변수를 지정하는 경우 변수명을 리스트로 감싸야 한다. 마지막으로 연산 규칙 또는 알고리즘은 대괄호 뒤에 적절한 메서드(.mean(), .agg() 등)를 사용하여 지정하며 Pandas 시리즈 객체에서 지원하는 메서드를 사용할 수 있다.

이제 기준 변수와 대상 변수가 각각 1개 할당된 형태의 기본형 코드로 .groupby() 메서드를 사용해보자. 연도(year)별 생산량(volumn)의 평균(mean)을 구하기 위한 코드는 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
df.groupby("year")["volumn"].mean()
## year
## 1990 1265.956667
## 1991 1316.827500
## 1992 1231.887500
## 1993 1255.200000
## 1994 1255.126667
## ...
## 2014 1250.789167
## 2015 1330.191667
## 2016 1301.994167
## 2017 1287.535000
## Name: volumn, dtype: float64

월(month)별 생산량(volumn)의 평균(mean)을 구하기 위한 코드는 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
df.groupby("month")["volumn"].mean()
## month
## 1 1320.243571
## 2 1301.081786
## 3 1238.140000
## 4 1182.153571
## 5 1166.146429
## 6 1192.766071
## 7 1188.485000
## 8 1279.288929
## 9 1349.205556
## 10 1493.850000
## 11 1517.335185
## 12 1511.517778
## Name: volumn, dtype: float64

실행 결과를 보면 기준변수가 결과 시리즈 객체의 인덱스에 위치한 것을 볼 수 있다. 그래서 인덱스 기반의 연산을 하지 않는다면 다음과 같이 .reset_index()를 사용해서 데이터프레임으로 객체 유형을 변경하기도 한다.

1
df.groupby("month")["volumn"].mean().reset_index()
month volumn
0 1 1320.243571
1 2 1301.081786
2 3 1238.140000
3 4 1182.153571
4 5 1166.146429
5 6 1192.766071
6 7 1188.485000
7 8 1279.288929
8 9 1349.205556
9 10 1493.850000
10 11 1517.335185
11 12 1511.517778

기준 변수 2개

이번에는 .groupby() 메서드에 2개의 기준 변수를 넣어보자. 데이터가 연도별 월별 데이터이기 때문에 기준변수에 연도와 월 변수를 넣는 것은 의미가 없어 2000년도 부터 최근까지 데이터를 1, 나머지를 0으로 하는 “is_2k” 변수를 추가로 만들고 진행하도록 한다.

1
2
df["is_2k"] = (df["year"] >= 2000) + 0
df.head(2)
year month volumn is_2k
0 1990 1 1199.87 0
1 1990 2 1214.54 0

기준 변수에 두 개 이상의 변수를 지정할 경우 리스트 객체로 만들어줘야 하기에 대괄호로 기준 변수명을 다음과 같이 묶어준다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
df.groupby(["is_2k", "year"])["volumn"].mean()
## is_2k year
## 0 1990 1265.956667
## 1991 1316.827500
## 1992 1231.887500
## 1993 1255.200000
## 1994 1255.126667
## 1995 1270.157500
## 1996 1322.317500
## 1997 1347.964167
## 1998 1425.135000
## 1999 1396.554167
## 1 2000 1462.280000
## 2001 1446.630000
## 2002 1385.381667
## ...

상기 결과를 보면 생성되는 시리즈 객체의 인덱스가 다중 인덱스(multi index)인 것을 알 수 있다. 역시 데이터프레임으로 변경하려면 .reset_index()를 사용한다.

1
df.groupby(["is_2k", "year"])["volumn"].mean().reset_index().head(14)
is_2k year volumn
0 0 1990 1265.956667
1 0 1991 1316.827500
2 0 1992 1231.887500
3 0 1993 1255.200000
4 0 1994 1255.126667
5 0 1995 1270.157500
6 0 1996 1322.317500
7 0 1997 1347.964167
8 0 1998 1425.135000
9 0 1999 1396.554167
10 1 2000 1462.280000
11 1 2001 1446.630000
12 1 2002 1385.381667
13 1 2003 1379.460833

대상 변수 2개

이번에는 .groupby() 메서드 다음에 2개의 대상 변수를 지정해보자. 그 전에 “vol2” 라는 수치형 변수를 하나 더 만들자.

1
2
df["vol2"] = round(df["volumn"] / 50)
df.head(2)
year month volumn is_2k vol2
0 1990 1 1199.87 0 24.0
1 1990 2 1214.54 0 24.0

다음과 같이 코드를 작성할 수 있다.

1
df.groupby("month")[["volumn", "vol2"]].mean()
volumn vol2
month
1 1320.243571 26.392857
2 1301.081786 26.000000
3 1238.140000 24.857143
4 1182.153571 23.678571
5 1166.146429 23.214286
6 1192.766071 23.892857
7 1188.485000 23.750000
8 1279.288929 25.607143
9 1349.205556 27.037037
10 1493.850000 29.962963
11 1517.335185 30.370370
12 1511.517778 30.296296

이렇게 대상변수가 2개 이상인 경우는 데이터프레임 객체를 반환한다.

.agg() 메서드의 사용

앞에는 .mean() 메서드만 사용했지만 한 번에 다양한 메서드를 사용하거나 Pandas에서 지원하지 않는 산술연산을 대상 변수에 적용하고자 할 때는 .agg() 메서드를 .groupby() 메서드에 이어서 사용할 수 있다.

다음과 같이 대상 변수가 하나이면서 .agg() 메서드에 하나의 연산 규칙만 지정하면 시리즈 객체가 반환되는 것을 볼 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
df.groupby("month")["volumn"].agg("mean")
## month
## 1 1320.243571
## 2 1301.081786
## 3 1238.140000
## 4 1182.153571
## 5 1166.146429
## 6 1192.766071
## 7 1188.485000
## 8 1279.288929
## 9 1349.205556
## 10 1493.850000
## 11 1517.335185
## 12 1511.517778
## Name: volumn, dtype: float64

대상 변수가 하나이면서 .agg() 메서드에 두 개 이상의 연산 규칙만 지정하면 데이터프레임 객체가 반환되는 것을 볼 수 있다. 그리고 연산 규칙이 2개 이상일 경우 리스트 객체를 사용해야하며 다음의 코드와 같다.

1
df.groupby("month")["volumn"].agg(["min", "max"])
min max
month
1 1078.80 1494.82
2 1067.80 1487.11
3 1026.72 1423.16
4 956.52 1391.38
5 963.02 1355.22
6 954.78 1384.00
7 987.75 1361.88
8 1062.75 1436.13
9 1126.87 1507.80
10 1368.72 1646.03
11 1390.49 1643.83
12 1221.21 1678.98

기타

.agg() 메서드의 경우 내부에 일회성 함수인 labmda 함수나 사용자 정의 함수를 사용하여 보다 다양한 연산을 수행할 수 있다. 하지만 해당 내용은 기초에서 살짝 벗어나기 때문에 향후 별도의 게시글에서 다루고자 한다.

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×