파이썬 기반 데이터분석을 위하여 .groupby()
메서드를 활용한 Pandas 객체의 요약을 알아본다.
※ 본 내용에서 사용하는 production_monthly_1990.csv 파일은 별도로 다운로드 받아야 한다.
※ production_monthly_1990.csv 다운받기 [클릭]
개요
Pandas 객체의 특정 변수를 요약하고자 하는 경우 .sum()
이나 .mean()
같은 메서드로 여러 요약 수치를 산출한다. 여기서 더 나아가 다른 변수를 기준으로 이런 요약 수치를 산출하는 작업이 필요할 수 있다. 예를 들어 월별 총 매출, 사용자별 구매상품 종류수 그리고 일별 최저기온 같은 수치가 있을 수 있다. 이러한 수치를 산출하고자 할 때는 월별로 데이터를 별도로 필터링할 수 있지만 이런 작업을 할 경우 중복되는 코드가 많아지거나 반복문을 써야하는 불편함이 있을 수 있다. 이 불편함을 해소해주는 메서드 중 하나가 .groupby()
메서드이다. 이제 groupby()
메서드에 대해 알아보도록 하자.
실습
실습을 위해 데이터를 준비하자.
1 | df = pd.read_csv("production_monthly_1990.csv") |
year | month | volumn | |
---|---|---|---|
0 | 1990 | 1 | 1199.87 |
1 | 1990 | 2 | 1214.54 |
만약 .groupby()
메서드를 사용하지 않는다면 다음과 같이 개별 코드를 작성하거나 반복문을 사용해서 처리해야 하니 참고하도록 하자.
1 | [df.loc[df["year"] == 1990, "volumn"].mean(), |
기본형
.groupby()
메서드는 메서드 내부에 데이터프레임의 특정 변수를 기준 변수로 해서 해당 변수를 기준으로 다른 변수의 요약 연산을 실시할 수 있도록 지원하는 메서드이다.
기준 변수의 경우 그 개수가 하나일 경우 단순 문자열로 입력하면 되나, 두 개 이상인 경우 변수명을 리스트로 감싼다. 그리고 요약 연산의 대상이 되는 변수는 메서드 뒤에 대괄호를 사용하여 명시하며 기준 변수와 같이 두 개 이상의 변수를 지정하는 경우 변수명을 리스트로 감싸야 한다. 마지막으로 연산 규칙 또는 알고리즘은 대괄호 뒤에 적절한 메서드(.mean()
, .agg()
등)를 사용하여 지정하며 Pandas 시리즈 객체에서 지원하는 메서드를 사용할 수 있다.
이제 기준 변수와 대상 변수가 각각 1개 할당된 형태의 기본형 코드로 .groupby()
메서드를 사용해보자. 연도(year)별 생산량(volumn)의 평균(mean)을 구하기 위한 코드는 다음과 같다.
1 | df.groupby("year")["volumn"].mean() |
월(month)별 생산량(volumn)의 평균(mean)을 구하기 위한 코드는 다음과 같다.
1 | df.groupby("month")["volumn"].mean() |
실행 결과를 보면 기준변수가 결과 시리즈 객체의 인덱스에 위치한 것을 볼 수 있다. 그래서 인덱스 기반의 연산을 하지 않는다면 다음과 같이 .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 | df["is_2k"] = (df["year"] >= 2000) + 0 |
year | month | volumn | is_2k | |
---|---|---|---|---|
0 | 1990 | 1 | 1199.87 | 0 |
1 | 1990 | 2 | 1214.54 | 0 |
기준 변수에 두 개 이상의 변수를 지정할 경우 리스트 객체로 만들어줘야 하기에 대괄호로 기준 변수명을 다음과 같이 묶어준다.
1 | df.groupby(["is_2k", "year"])["volumn"].mean() |
상기 결과를 보면 생성되는 시리즈 객체의 인덱스가 다중 인덱스(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 | df["vol2"] = round(df["volumn"] / 50) |
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 | df.groupby("month")["volumn"].agg("mean") |
대상 변수가 하나이면서 .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 함수나 사용자 정의 함수를 사용하여 보다 다양한 연산을 수행할 수 있다. 하지만 해당 내용은 기초에서 살짝 벗어나기 때문에 향후 별도의 게시글에서 다루고자 한다.
<파이썬 데이터분석 기초 시리즈>
01 - 원소
02 - 연산자
03 - 함수
04 - 객체(리스트)
05 - 객체(튜플)
06 - 객체(딕셔너리)
07 - 객체(세트)
08 - 객체(기타)
09 - 제어문(if)
10 - 제어문(for)
11 - 기본함수
12 - 라이브러리
13 - 경로
14 - NumPy
15 - Pandas
16 - Pandas(Series)
17 - Pandas(DataFrame)
18 - Pandas(객체 탐색)
19 - Pandas(원소/조합 세기)
20 - Pandas(파일 읽어오기)
21 - Pandas(파일 쓰기)
22 - Pandas(필터링)
23 - Pandas(수치연산)
24 - Pandas(신규 변수 생성)
25 - Pandas(시간 데이터)
26 - Pandas(문자 데이터)
27 - Pandas(결측값 처리)
28 - Pandas(정렬)
29 - Pandas(GroupBy)
30 - Pandas(Apply)
31 - Pandas(Crosstab)
32 - Pandas(Melt)
33 - Pandas(Pivoting)
34 - Pandas(Merge)
35 - Pandas(그래프)