Pandas 데이터 정렬
.sort_values()
import pandas as pd
data = {
'name' : ['홍지혜', '이아희', '장나영', '이시연'],
'age' : [25, 27, 23, 24],
'position' : ['Q', 'W', 'E', 'R'],
'instrument' : ['drum', 'bass', 'guitar', 'vocal']
}
df = pd.DataFrame(data)
df
name | age | position | instrument | |
---|---|---|---|---|
0 | 홍지혜 | 25 | Q | drum |
1 | 이아희 | 27 | W | bass |
2 | 장나영 | 23 | E | guitar |
3 | 이시연 | 24 | R | vocal |
나이로 정렬
sorted_df = df.sort_values(by = 'age')
이름으로 정렬
sorted_df2 = df.sort_values(by = 'name', ascending = False)
# 기본 오름차순
# ascending = False 내림차순
name | age | position | instrument | |
---|---|---|---|---|
0 | 홍지혜 | 25 | Q | drum |
2 | 장나영 | 23 | E | guitar |
1 | 이아희 | 27 | W | bass |
3 | 이시연 | 24 | R | vocal |
여러 조건을 적용한 정렬
data2 = {
'name' : ['홍지혜', '이아희', '장나영', '이시연', '바위게'],
'age' : [25, 27, 23, 24, 27],
'position' : ['Q', 'W', 'E', 'R', 'Fan'],
'instrument' : ['drum', 'bass', 'guitar', 'vocal', 'light stick']
}
df2 = pd.DataFrame(data2)
sorted_df3 = df2.sort_values(by = ['age', 'name'], ascending = [False, True])
# 나이는 내림차순, 이름은 오름차순(앞에 있는 조건이 우선 반영)
sorted_df3
name | age | position | instrument | |
---|---|---|---|---|
4 | 바위게 | 27 | Fan | light stick |
1 | 이아희 | 27 | W | bass |
0 | 홍지혜 | 25 | Q | drum |
3 | 이시연 | 24 | R | vocal |
2 | 장나영 | 23 | E | guitar |
# 결과 = 나이를 기준으로 내림차순 후, 같은 나이인 경우 이름을 기준으로 오름차순으로 정렬
.sort_index()
sorted_df3.sort_index()
#인덱스를 기준으로 정렬
name | age | position | instrument | |
---|---|---|---|---|
0 | 홍지혜 | 25 | Q | drum |
1 | 이아희 | 27 | W | bass |
2 | 장나영 | 23 | E | guitar |
3 | 이시연 | 24 | R | vocal |
4 | 바위게 | 27 | Fan | light stick |
.merge()
SQL inner join과 유사, 공통 열을 기준으로 병합
data3 = {
'name' : ['홍지혜', '이아희', '장나영', '이시연'],
'alias' : ['Chodan', 'Magenta', 'Hina', 'Siyeon']
}
df3 = pd.DataFrame(data3)
merged_df = pd.merge(df2, df3, on ='name')
# 공통되지 않는 데이터('바위게')는 지우고 병합
merged_df
name | age | position | instrument | alias | |
---|---|---|---|---|---|
0 | 홍지혜 | 25 | Q | drum | Chodan |
1 | 이아희 | 27 | W | bass | Magenta |
2 | 장나영 | 23 | E | guitar | Hina |
3 | 이시연 | 24 | R | vocal | Siyeon |
.merge() 조건 설정
merge_df2 = pd.merge(df2, df3, on = 'name', how='left')
# 왼쪽을 데이터 유지, 없는 값은 NaN 으로 표시
# 모든 행을 유지하려면 how = outer, 겹치는 부분만 inner
# sql left join
# right 도 가능
name | age | position | instrument | alias | |
---|---|---|---|---|---|
0 | 홍지혜 | 25 | Q | drum | Chodan |
1 | 이아희 | 27 | W | bass | Magenta |
2 | 장나영 | 23 | E | guitar | Hina |
3 | 이시연 | 24 | R | vocal | Siyeon |
4 | 바위게 | 27 | Fan | light stick | NaN |
merge 주의점 = 중복값이 생길 수 있음
.concat()
# 데이터 프레임을 서로 연결
data4 = {
'name' : ['김계란', '차정원', '고윤하', '전소연'],
'position' : ['producer', 'teacher', 'mentor', 'director']
}
df4 = pd.DataFrame(data4)
행으로 연결
concat_df = pd.concat([df, df4], axis = 0) # 행단위
concat_df
name | age | position | instrument | |
---|---|---|---|---|
0 | 홍지혜 | 25.0 | Q | drum |
1 | 이아희 | 27.0 | W | bass |
2 | 장나영 | 23.0 | E | guitar |
3 | 이시연 | 24.0 | R | vocal |
0 | 김계란 | NaN | producer | NaN |
1 | 차정원 | NaN | teacher | NaN |
2 | 고윤하 | NaN | mentor | NaN |
3 | 전소연 | NaN | director | NaN |
열로 연결
concat_df2 = pd.concat([df, df4], axis = 1) # 열단위
concat_df2
name | age | position | instrument | name | position | |
---|---|---|---|---|---|---|
0 | 홍지혜 | 25 | Q | drum | 김계란 | producer |
1 | 이아희 | 27 | W | bass | 차정원 | teacher |
2 | 장나영 | 23 | E | guitar | 고윤하 | mentor |
3 | 이시연 | 24 | R | vocal | 전소연 | director |
.set_index() & .join()
인덱스를 설정한 후 정렬, 해당 인덱스를 기준으로 데이터 병합
df = df.set_index('position')
df
name | age | instrument | |
---|---|---|---|
position | |||
Q | 홍지혜 | 25 | drum |
W | 이아희 | 27 | bass |
E | 장나영 | 23 | guitar |
R | 이시연 | 24 | vocal |
df5 = pd.DataFrame({'from' : ['twitch', 'twitch', 'tiktok', 'NMB48']},
index = ['Q', 'W', 'E', 'R'])
df.join(df5)
name | age | instrument | from | |
---|---|---|---|---|
position | ||||
Q | 홍지혜 | 25 | drum | twitch |
W | 이아희 | 27 | bass | twitch |
E | 장나영 | 23 | guitar | tiktok |
R | 이시연 | 24 | vocal | NMB48 |
.groupby()
import pandas as pd
data = {
'이름': ['김도영', '로하스', '송성문', '김도영', '로하스', '송성문'],
'출루' : ['안타', '안타', '안타', '볼넷', '볼넷', '볼넷'],
'개수' : [189, 188, 179, 66, 88, 64]
}
df = pd.DataFrame(data)
grouped = df.groupby('이름')
# 이름으로 그룹화
grouped['개수'].mean()
# 개수의 평균을 구함
#
이름
김도영 127.5
로하스 138.0
송성문 121.5
Name: 개수, dtype: float64
grouped_multi = df.groupby(['이름', '출루'])['개수'].sum()
# 이름과 출루로 그룹화 후 개수의 각 합을 구함
grouped_multi
#
이름 출루
김도영 볼넷 66
안타 189
로하스 볼넷 88
안타 188
송성문 볼넷 64
안타 179
Name: 개수, dtype: int64
.agg()
.agg() 다중집계작업 메서드
# aggregate
.apply()와 비슷하지만 여러개의 함수를 동시에 적용 가능
df.agg(func=None, axis=0, args, kwargs) 형태
grouped['개수'].agg(['sum','mean'])
# 합과 평균을 동시에 적용
sum | mean | |
---|---|---|
이름 | ||
김도영 | 255 | 127.5 |
로하스 | 276 | 138.0 |
송성문 | 243 | 121.5 |
.pivot_table()
pivot = pd.pivot_table(df, index = '이름', columns = '출루', values ='개수', aggfunc = ['sum','mean'], fill_value=0, margins = True)
# 행, 열, 열에 들어갈 데이터, 집계방식, 결측치에 넣을 값, margins 을 통해 합계 표시 여부
pivot #없는 데이터는 NaN
sum | mean | |||||
---|---|---|---|---|---|---|
출루 | 볼넷 | 안타 | All | 볼넷 | 안타 | All |
이름 | ||||||
김도영 | 66 | 189 | 255 | 66.000000 | 189.000000 | 127.5 |
로하스 | 88 | 188 | 276 | 88.000000 | 188.000000 | 138.0 |
송성문 | 64 | 179 | 243 | 64.000000 | 179.000000 | 121.5 |
All | 218 | 556 | 774 | 72.666667 | 185.333333 | 129.0 |
특정 열에 각각 다른 집계 적용
agg_reult = df.groupby('이름').agg({'개수' : ['sum', 'max', 'min']})
# 이름으로 그룹화, 개수에 각각 합, 최댓값, 최솟값을 적용해 조회
agg_reult
개수 | |||
---|---|---|---|
sum | max | min | |
이름 | |||
김도영 | 255 | 189 | 66 |
로하스 | 276 | 188 | 88 |
송성문 | 243 | 179 | 64 |
df.groupby('이름').agg('sum').sort_values(by='개수')
# 이름으로 그룹화 값의 합을 조회하고 개수의 오름차순으로 정렬
출루 | 개수 | |
---|---|---|
이름 | ||
송성문 | 안타볼넷 | 243 |
김도영 | 안타볼넷 | 255 |
로하스 | 안타볼넷 | 276 |
결측치, 이상치, 중복값 처리
데이터 전처리, 결측치, 이상치 처리, 인코딩 등
ai 발전으로 비정형 데이터 처리 중요성이 커짐
import pandas as pd
data = {
'name' : ['아이유', '이지금', '이지은', '이지동'],
'age' : [16, 7, 31, None],
'job' : ['celebrity', 'youtuber', 'celebrity', 'office worker']
}
df = pd.DataFrame(data)
df
name | age | job | |
---|---|---|---|
0 | 아이유 | 16.0 | celebrity |
1 | 이지금 | 7.0 | youtuber |
2 | 이지은 | 31.0 | celebrity |
3 | 이지동 | NaN | office worker |
결측치 확인
df.isna().sum()
# 결측치인 경우의 합
# 결측치인 경우 = True = 1
#
name 0
age 1
job 0
dtype: int64
# age 컬럼에 결측치 1개 존재
df.loc[(df['job'] == 'celebrity') & (~df['age'].isna()), 'name']
# 직업이 유명인이고 나이가 결측치가 아닌 사람의 이름을 출력
#
0 아이유
2 이지은
Name: name, dtype: object
결측치 제거
df_dropped = df.dropna(axis = 0) # axis = 0 행삭제, 1 열 삭제
df_dropped # 결측치가 있는 행 제거
name | age | job | |
---|---|---|---|
0 | 아이유 | 16.0 | celebrity |
1 | 이지금 | 7.0 | youtuber |
2 | 이지은 | 31.0 | celebrity |
결측치 대체
df_filled = df.fillna('모름')
df_filled
#
df['age'] = df['age'].fillna(df['age'].mean())
# 결측치를 나이의 평균값으로 채움
name | age | job | |
---|---|---|---|
0 | 아이유 | 16.0 | celebrity |
1 | 이지금 | 7.0 | youtuber |
2 | 이지은 | 31.0 | celebrity |
3 | 이지동 | 모름 | office worker |
결측치 보간 (주변값 참조하여 결측치 보완)
data = {
'날짜': pd.date_range('2024-01-01', periods=5),
'온도': [20, 22, None, 24, 25]
}
df2 = pd.DataFrame(data)
df2['온도'] = df2['온도'].interpolate()
# .interplate() 보간법(기본값은 선형보간법)
df2
날짜 | 온도 | |
---|---|---|
0 | 2024-01-01 | 20.0 |
1 | 2024-01-02 | 22.0 |
2 | 2024-01-03 | 23.0 |
3 | 2024-01-04 | 24.0 |
4 | 2024-01-05 | 25.0 |
data3 = {
'name' : ['아이유', '이지금', '이지은', '이지동'],
'age' : [16, 7, 31, None],
'job' : ['celebrity', 'youtuber', 'celebrity', 'office worker']
}
df3 =pd.DataFrame(data3)
df2.loc[(df2['job'] == 'office worker') & (df2['age'].isna()), 'age'] = 20
# 직업이 회사원이고 나이가 결측치인 것은 20으로 대체
또는
def fill_nan_age(x):
if pd.isna(x):
return 20
return x
# 나이 데이터에 결측치를 20으로 채워라
df3['age'] = df3['age'].apply(fill_nan_age)
print(df3)
#
name age job
0 아이유 16.0 celebrity
1 이지금 7.0 youtuber
2 이지은 31.0 celebrity
3 이지동 20.0 office worker
결측치를 채우는 방법은 간단, 어떻게 채우는지가 중요 나이를 단순히 평균으로 취하는 것과 직업(예를 들어 학생)을 참고하여 채우는 것은 차이가 있다