Pandas 데이터 정렬

TIL Day 13

By polaris0208

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

결측치를 채우는 방법은 간단, 어떻게 채우는지가 중요 나이를 단순히 평균으로 취하는 것과 직업(예를 들어 학생)을 참고하여 채우는 것은 차이가 있다