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)
|
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)
pivot
|
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()
name 0
age 1
job 0
dtype: int64
df.loc[(df['job'] == 'celebrity') & (~df['age'].isna()), 'name']
0 아이유
2 이지은
Name: name, dtype: object
결측치 제거
df_dropped = df.dropna(axis = 0)
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()
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
또는
def fill_nan_age(x):
if pd.isna(x):
return 20
return x
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
결측치를 채우는 방법은 간단, 어떻게 채우는지가 중요
나이를 단순히 평균으로 취하는 것과 직업(예를 들어 학생)을 참고하여 채우는 것은 차이가 있다