Pandas는 데이터에 대한 다양한 기능을 제공한다.
오늘은 그 중에 데이터를 정렬하고 병합하는 기능에 대해 살펴보고자 한다.
또한 다양한 데이터프레임을 결합해서 원하는 새로운 데이터프레임을 만들어보자.
데이터 분석의 기본. 데이터 정렬
- sort_values()를 사용해서 값(value)을 기준으로 정렬하기
import pandas as pd
# 데이터프레임 생성
data = {
'이름': ['철수', '영희', '민수', '지수'],
'나이': [25, 30, 22, 35],
'직업': ['학생', '회사원', '학생', '프리랜서']
}
df = pd.DataFrame(data)
print(df)
"""
이름 나이 직업
0 철수 25 학생
1 영희 30 회사원
2 민수 22 학생
3 지수 35 프리랜서
"""
# '나이' 기준으로 오름차순 정렬
sorted_df = df.sort_values(by='나이')
print(sorted_df)
"""
이름 나이 직업
2 민수 22 학생
0 철수 25 학생
1 영희 30 회사원
3 지수 35 프리랜서
"""
- 내림차순으로 정렬하려면, ascending=False로 지정하기
# '나이' 기준으로 내림차순 정렬
sorted_df = df.sort_values(by='나이', ascending=False)
print(sorted_df)
"""
이름 나이 직업
3 지수 35 프리랜서
1 영희 30 회사원
0 철수 25 학생
2 민수 22 학생
"""
- sort_values()를 사용해 여러 열을 기준으로 정렬하기
- 열 기준으로 정렬 순서 각각 다르게 지정하기
import pandas as pd
data = {
'이름': ['철수', '영희', '민수', '지수', '민재'],
'나이': [25, 30, 22, 35, 30],
'직업': ['학생', '회사원', '학생', '프리랜서', '축구선수']
}
df = pd.DataFrame(data)
print(df)
"""
이름 나이 직업
0 철수 25 학생
1 영희 30 회사원
2 민수 22 학생
3 지수 35 프리랜서
4 민재 30 축구선수
"""
# '나이'를 기준으로, 같은 나이 내에서 '이름' 오름차순 정렬
sorted_df_3 = df.sort_values(by=['나이', '이름'])
print(sorted_df_3)
"""
이름 나이 직업
2 민수 22 학생
0 철수 25 학생
4 민재 30 축구선수
1 영희 30 회사원
3 지수 35 프리랜서
"""
# '나이'를 기준으로 내림차순 정렬 후, 같은 나이 내에서 '이름' 내림차순 정렬
sorted_df_4 = df.sort_values(by=['나이', '이름'], ascending=False)
print(sorted_df_4)
"""
이름 나이 직업
3 지수 35 프리랜서
1 영희 30 회사원
4 민재 30 축구선수
0 철수 25 학생
2 민수 22 학생
"""
# '나이'를 기준으로 내림차순 정렬 후, 같은 나이 내에서 '이름'을 오름차순 정렬
sorted_df_5 = df.sort_values(by=['나이', '이름'], ascending=[False, True])
print(sorted_df_5)
"""
이름 나이 직업
3 지수 35 프리랜서
4 민재 30 축구선수
1 영희 30 회사원
0 철수 25 학생
2 민수 22 학생
"""
- sort_index()를 사용해 인덱스 기준으로 정렬하기
print(sorted_df)
"""
이름 나이 직업
3 지수 35 프리랜서
1 영희 30 회사원
4 민재 30 축구선수
0 철수 25 학생
2 민수 22 학생
"""
# 인덱스를 기준으로 정렬
sorted_df.sort_index()
"""
이름 나이 직업
0 철수 25 학생
1 영희 30 회사원
2 민수 22 학생
3 지수 35 프리랜서
4 민재 30 축구선수
"""
# 인덱스를 기준으로 내림차순 정렬
sorted_df.sort_index(ascending=False)
"""
이름 나이 직업
4 민재 30 축구선수
3 지수 35 프리랜서
2 민수 22 학생
1 영희 30 회사원
0 철수 25 학생
"""
여러 개의 데이터 병합
- merge()를 사용해 공통 열을 기준으로 데이터프레임 병합(≒SQL의 INNER JOIN)
※ 공통값이 없는 데이터는 삭제됨에 주의
df1 = pd.DataFrame({
'이름': ['철수', '영희', '민수'],
'나이': [25, 30, 22]
})
print(df1)
'''
이름 나이
0 철수 25
1 영희 30
2 민수 22
'''
df2 = pd.DataFrame({
'이름': ['철수', '영희', '지수'],
'직업': ['학생', '회사원', '프리랜서']
})
print(df2)
'''
이름 직업
0 철수 학생
1 영희 회사원
2 지수 프리랜서
'''
# "이름"을 기준으로 병합
merge_df = pd.merge(df1, df2, on = '이름')
'''
print(merge_df)
이름 나이 직업
0 철수 25 학생
1 영희 30 회사원
'''
# 공통값이 아닌 '민수'와 '지수'의 데이터는 삭제됨
그렇다면 삭제된 데이터를 유지하려면 어떻게 해야 될까?
how = "left" / how = "right" / how = "outer" 값을 지정하기
# left(df1)을 기준으로 데이터를 유지하되, 없는 데이터는 NaN으로 출력
merge_df = pd.merge(df1, df2, on="이름", how = "left")
print(merge_df)
'''
이름 나이 직업
0 철수 25 학생
1 영희 30 회사원
2 민수 22 NaN
'''
# right(df2)을 기준으로 데이터를 유지하되, 없는 데이터는 NaN으로 출력됨
merge_df = pd.merge(df1, df2, on="이름", how = "right")
print(merge_df)
'''
이름 나이 직업
0 철수 25.0 학생
1 영희 30.0 회사원
2 지수 NaN 프리랜서
'''
# 모든 행의 데이터를 유지하되, 없는 데이터는 NaN으로 출력됨
merge_df = pd.merge(df1, df2, on="이름", how = "outer")
print(merge_df)
'''
이름 나이 직업
0 민수 22.0 NaN
1 영희 30.0 회사원
2 지수 NaN 프리랜서
3 철수 25.0 학생
'''
- concat()을 사용해 행 또는 열 단위로 데이터프레임 연결하기
print(df1)
'''
이름 나이
0 철수 25
1 영희 30
2 민수 22
'''
print(df2)
'''
이름 직업
0 철수 학생
1 영희 회사원
2 지수 프리랜서
'''
# 행 단위(axis=0)로 데이터프레임 연결
concat_df = pd.concat([df1, df2], axis=0)
print(concat_df)
'''
이름 나이 직업
0 철수 25.0 NaN
1 영희 30.0 NaN
2 민수 22.0 NaN
0 철수 NaN 학생
1 영희 NaN 회사원
2 지수 NaN 프리랜서
'''
# 열 단위(axis=1)로 데이터프레임 연결
concat_df = pd.concat([df1, df2], axis=1)
print(concat_df)
'''
이름 나이 이름 직업
0 철수 25 철수 학생
1 영희 30 영희 회사원
2 민수 22 지수 프리랜서
'''
- join()을 사용해 인덱스를 기준으로 데이터프레임 병합하기
print(df1)
'''
이름 나이
0 철수 25
1 영희 30
2 민수 22
'''
df3 = pd.DataFrame({
'직업': ['학생', '회사원', '프리랜서'],
'연봉': [2000, 3000, 4000]
}, index=['철수', '영희', '지수'])
print(df3)
'''
직업 연봉
철수 학생 2000
영희 회사원 3000
지수 프리랜서 4000
'''
df1 = df1.set_index('이름') # '이름'열을 인덱스로 설정
print(d1)
'''
나이
이름
철수 25
영희 30
민수 22
'''
# 인덱스를 기준으로 병합
df1.join(df3)
'''
나이 직업 연봉
이름
철수 25 학생 2000.0
영희 30 회사원 3000.0
민수 22 NaN NaN
'''
데이터 그룹화 및 집계
- groupby() 함수를 사용해 특정 열 기준으로 그룹화
import pandas as pd
data = {
'이름': ['철수', '영희', '민수', '지수', '철수', '영희'],
'과목': ['수학', '수학', '과학', '과학', '영어', '영어'],
'점수': [90, 85, 95, 80, 75, 88]
}
df = pd.DataFrame(data)
print(df)
'''
이름 과목 점수
0 철수 수학 90
1 영희 수학 85
2 민수 과학 95
3 지수 과학 80
4 철수 영어 75
5 영희 영어 88
'''
grouped = df.groupby('이름') # '이름'을 기준으로 그릅화
- 집계 함수를 사용해서 다양한 요약 통계 계산하기
# 그룹에 대한('이름'을 기준) 각 학생의 평균 점수 계산
grouped['점수'].mean()
'''
이름
민수 95.0
영희 86.5
지수 80.0
철수 82.5
Name: 점수, dtype: float64
'''
# 그룹에 대한 각 학생의 점수 합계와 평균 계산
grouped['점수'].agg(['sum', 'mean']) # 여러 집계 함수 동시에 사용
'''
sum mean
이름
민수 95 95.0
영희 173 86.5
지수 80 80.0
철수 165 82.5
'''
- 여러 열을 기준으로 그룹화하기
print(df)
'''
이름 과목 점수
0 철수 수학 90
1 영희 수학 85
2 민수 과학 95
3 지수 과학 80
4 철수 영어 75
5 영희 영어 88
'''
# '이름'과 '과목'을 기준으로 그룹화 후 점수 합계를 계산
grouped_multi = df.groupby(['이름', '과목'])['점수'].sum()
print(grouped_multi)
'''
print(grouped_multi)
이름 과목
민수 과학 95
영희 수학 85
영어 88
지수 과학 80
철수 수학 90
영어 75
Name: 점수, dtype: int64
'''
데이터를 요약하고 분석해주는 피벗테이블 사용하기
- pivot_table() 함수 사용하기
# 이름 별 과목의 점수 평균을 계산하는 피벗 테이블 생성
pivot = pd.pivot_table(df, index = '이름', columns = '과목', values = '점수', aggfunc = 'mean')
print(pivot)
'''
과목 과학 수학 영어
이름
민수 95.0 NaN NaN
영희 NaN 85.0 88.0
지수 80.0 NaN NaN
철수 NaN 90.0 75.0
'''
여러 집계 함수를 사용하고 싶다면?
aggfunc에 여러 집계 함수를 지정해주면 된다.
# 점수의 평균과 점수의 합계를 계산하는 피벗 테이블 생성
pivot_multi = pd.pivot_table(df, index = '이름', columns = '과목', values = '점수', aggfunc =['mean', 'sum'])
print(pivot_multi)
'''
mean sum
과목 과학 수학 영어 과학 수학 영어
이름
민수 95.0 NaN NaN 95.0 NaN NaN
영희 NaN 85.0 88.0 NaN 85.0 88.0
지수 80.0 NaN NaN 80.0 NaN NaN
철수 NaN 90.0 75.0 NaN 90.0 75.0
'''
- margins = True를 사용해 각 행과 열의 전체 합계 추가하기
pivot_multi = pd.pivot_table(df, index = '이름', columns = '과목', values = '점수', aggfunc =['mean', 'sum'], margins = True)
print(pivot_multi)
'''
mean sum
과목 과학 수학 영어 All 과학 수학 영어 All
이름
민수 95.0 NaN NaN 95.0 95.0 NaN NaN 95
영희 NaN 85.0 88.0 86.5 NaN 85.0 88.0 173
지수 80.0 NaN NaN 80.0 80.0 NaN NaN 80
철수 NaN 90.0 75.0 82.5 NaN 90.0 75.0 165
All 87.5 87.5 81.5 85.5 175.0 175.0 163.0 513
'''
※ 평균에 대해선 평균의 총 합이 아닌 전체 합계에 대한 평균을 보여줌에 주의해야 함
- fill_value = 0 값을 지정해서 피벗 테이블의 결측치(NaN)를 0으로 치환하기
pivot_multi = pd.pivot_table(df, index = '이름', columns = '과목', values = '점수', aggfunc =['mean', 'sum'], margins = True, fill_value = 0)
print(pivot_multi)
'''
mean sum
과목 과학 수학 영어 All 과학 수학 영어 All
이름
민수 95.0 0.0 0.0 95.0 95 0 0 95
영희 0.0 85.0 88.0 86.5 0 85 88 173
지수 80.0 0.0 0.0 80.0 80 0 0 80
철수 0.0 90.0 75.0 82.5 0 90 75 165
All 87.5 87.5 81.5 85.5 175 175 163 513
'''
- 모든 그룹이 아닌 특정한 열의 집계 함수만 구하기
import pandas as pd
data = {
'이름': ['철수', '영희', '민수', '지수', '철수', '영희'],
'과목': ['수학', '수학', '과학', '과학', '영어', '영어'],
'점수': [90, 85, 95, 80, 75, 88],
'나이': [15, 14, 13, 12, 13, 12]
}
df = pd.DataFrame(data)
print(df)
'''
이름 과목 점수 나이
0 철수 수학 90 15
1 영희 수학 85 14
2 민수 과학 95 13
3 지수 과학 80 12
4 철수 영어 75 13
5 영희 영어 88 12
'''
# 딕셔너리 형태로 agg에 필요한 집계 함수만 전달
agg_result = df.groupby('이름').agg({
'점수':['mean', 'sum', 'max'],
'나이':['max', 'sum']
})
print(agg_result)
'''
점수 나이
mean sum max max sum
이름
민수 95.0 95 95 13 13
영희 86.5 173 88 14 26
지수 80.0 80 80 12 12
철수 82.5 165 90 15 28
'''