파이썬/Pandas

5.Pandas 추가 메서드 - 2

잘잔디 2023. 5. 2. 10:15

DataFrame fillna() 메서드

  • fillna() 메서드는 NaN값을 원하는 값으로 바꿀 수 있다. 첫 인자로 변경하고자 하는 값을 전달하면 된다.
  • value값으로 column label을 key로 갖는 딕셔너리를 전달하여 column마다 NaN을 대치하는 값을 각각 설정가능.
  • limit 키워드 인자에 숫자를 전달하여 그 숫자만큼 column마다 변경 횟수를 제한할 수 있다.
  • DataFrame을 value로 전달해서 NaN값을 대체할 수 있습니다. 다만 column label과 row index가 일치하지 않으면 적용되지 않는다.
# np.nan 으로 NaN값 만들 수 있음.
df = pd.DataFrame([[np.nan,2,np.nan,0],
                  [3,4,np.nan,1],
                  [np.nan,np.nan,np.nan,np.nan],
                  [np.nan,3,np.nan,4]], columns = list('ABCD'))
print(df)
print(df.fillna(0))

values = {'A':0,'B' :1,'C':2,'D':3} #column마다 원하는 값으로 NaN값을 채울 수 있다.
df.fillna(value=values)

df.fillna(value=values,limit=2) # column마다 2회씩만 변경가능.

df2 = pd.DataFrame(np.zeros((3,4)),columns = list('ABCㅎ')) # column도 ㅎ column이 D와 일치하지 않아서 NaN이 남아있음.
df.fillna(df2)                                              
# row도 한줄 짧아서 마지막 row는 NaN이 그대로 남아있음

A B C D

0 0.0 2.0 0.0 0.0
1 3.0 4.0 0.0 1.0
2 0.0 0.0 0.0 NaN
3 NaN 3.0 NaN 4.0
#연습문제1
avg_age = int(titanic['age'].mean()) # 평균값 구함

titanic['age'] = titanic['age'].fillna(avg_age) # fillna에 inplace=True를 넣어주면 할당하지 않고도 알아서 바뀐값이 저장됨.
# print(titanic[titanic['age'].isna()])# age에 NaN값이 없음을 볼 수 있음\\
titanic.head(15)
titanic.count()

DataFrame astype() 메서드

  • column의 자료형을 변경하는 메서드

d = {'col1' : [1,2], 'col2' : [3,4]}
df = pd.DataFrame(data=d)
df.dtypes

df.astype('int32').dtypes

df.astype({'col1': 'int32'}).dtypes # dictionary로 지정하여 하나씩 타입변경 가능

 

titanic['category2'] = titanic['sex'] + titanic['age'].astype('str')
titanic[['age','category2']]

DataFrame 실수 값을 카테고리 값으로 변환

  • 실수 값을 크기 기준으로 하여 카테고리 값으로 변환하고 싶을 떄는 다음과 같은 명령을 사용합니다.
  • cut : 실수 값의 경계선을 지정하는 경우 - 범위단위로 끊을때 유리
    • x = 1차원 형태의 배열 형태가 옵니다.
    • bins = int, 스칼라를 요소로 갖는 시퀀스가 옵니다.
  • qcut : 개수가 똑같은 구간으로 나누는 경우(분위수) - 개수단위로 끊을 때 유리
    • x = id ndarray 호은 Series
    • q = int 혹은 분위수를 나타내는 1.이하의 실수를 요소로 갖는 list (ex. [0,. 25 ,. 5 ,. 75, 1.])
ages = [0,2,10,21,23,37,31,61,20,41,32,90,101]
bins = [1,20,30,50,70,100]
label = ['미성년자','청년','장년','중년','노년']
cats = pd.cut(ages,bins,labels = label)
cats      #구간내에 없다면 NaN값이 들어간다.

print(type(cats)) # cut 명령이 반환하는 값은 categorical type이다.
                  # 속성으로 label 문자열을 codes 속성으로 정수로 인코딩한 카테고리 값을 가집니다.
print(cats.categories)
print(cats.codes) # 없으면 -1로 반환함.

df4 = pd.DataFrame(ages,columns = ['ages'])
df4['age_cat'] = pd.cut(df4.ages,bins,labels=label)
print(df4.dtypes)        
# category 데이터는 문자열 취급이 안된다.(object type임)

df4['age_cat'].astype(str) + df4['ages'].astype(str)# 문자열로 쓰기 위해서는 astype해주는 과정이 필요함.
print(df4.dtypes)

df4

ages   age_cat

0 0 NaN
1 2 미성년자
2 10 미성년자
3 21 청년
4 23 청년
5 37 장년
6 31 장년
7 61 중년
8 20 미성년자
9 41 장년
10 32 장년
11 90 노년
12 101 NaN
# qcut은 원하는 개수만큼 여기서는 4개 구간으로 나누어
data = np.random.randn(1000)
cats = pd.qcut(data, 4 , labels=['Q1','Q2','Q3','Q4'])
print(pd.value_counts(cats)) #같은 개수로 나누어 짐을 알 수 있다.
cats

bins = [0,20,30,50,70,100]
labels = ["미성년자", "청년", "장년", "중년", "노년"]
cuts = pd.cut(titanic['age'],bins,labels = label)
sorted_value_count = pd.value_counts(cuts).sort_index()
print(sorted_value_count)
sorted_value_count / sum(sorted_value_count)

 

DataFrame 인덱스 설정 및 제거

  • set_index = 기존의 row 인덱스를 제거하고 데이터 column 중 하나를 인덱스로 설정합니다.
  • reset_index =기존의 row 인덱스를 제거하고 인덱스를 데이터 열로 추가합니다.
import numpy as np
import pandas as pd
np.random.seed(0)
df1 = pd.DataFrame(np.vstack([list('ABCDE'), np.round(np.random.rand(3,5),2)]).T , columns = ['c1','c2','c3','c4'])
print(df1)

df2 = df1.set_index('c1')
print(df2)

df2.set_index('c2') # 기존의 인덱스는 사라진다.

 

  c3  c4
c2    
0.55 0.65 0.79
0.72 0.44 0.53
0.6 0.89 0.57
0.54 0.96 0.93
0.42 0.38 0.07
  • reset_index 메서드를 쓰면 보통의 자료열로 바꿀 수도 있다. 이떄 index column은 자료열의 가장 선두로 삽입됩니다.
    • 인수중에 drop = True로 인수를 전달하면 인덱스 column을 보통의 자료열로 올리는 것이 아니라 그냥 버리게 된다.
  • DataFrame의 인덱스는 정수로 된 디폴트 인덱스로 바뀝니다.
print(df2)
print(df2.reset_index())

print(df2)df2.reset_index(drop = True)

score = {
    "이름":["일식", "이식", "삼식", "사식", "오식"],
    "국어":[60, 70, 90, 80, 100],
    "영어":[70, 86, 82, 88, 100],
    "수학":[65, 82, 85, 90, 100]
}
scores = pd.DataFrame(score)
scores

inplace = True 를 사용하여 만듬과 동시에 할당도 가능하다.

scores.set_index('이름',inplace = True)scores

국어 영어 수학

이름      
일식 60 70 65
이식 70 86 82
삼식 90 82 85
사식 80 88 90
오식 100 100 100
scores.reset_index(inplace = True)scores

이름 국어 영어 수학

0 일식 60 70 65
1 이식 70 86 82
2 삼식 90 82 85
3 사식 80 88 90
4 오식 100 100 100

DataFrame 다중 인덱스

  • row나 column에 여러 계층을 가지는 인덱스 즉, 다중 인덱스를 설정할 수도 있습니다.
  • DataFrame을 생성할 때 columns 인수에 당므 예제처럼 리스트의 리스트(행렬) 형태로 인덱스를 넣으면 다중 열 인덱스를 가지게 된다.
  • 이름을 지정하면 더 편리하게 사용할 수 있습니다. column 인덱스들의 이름 지정은 columns 객체의 names 속성에 리스트를 넣어서 지정합니다.
  • 다중 인덱스는 이름을 지정하면 더 편리한 사용이 가능하다. column 인덱스들의 이름 지정은 columns.names에 리스트를 넣어서 지정 가능하다.
np.random.seed(0)
df3 = pd.DataFrame(np.round(np.random.randn(5,4),2)
                   ,columns = [['A','A','B','B'],
                                ['C1','C2','C1','C2']])
df3

df3.columns.names = ['Cidx1','Cidx2']
df3

np.random.seed(0)
df4 = pd.DataFrame(np.round(np.random.randn(6,4),2),
                    columns = [['A','A','B','B'],
                                ['C1','C2','C1','C2']],
                    index = [['M','M','M','F','F','F'],
                            ['id_' + str(i+1) for i in range(3)] * 2])
df4.columns.names = ['Cidx1','Cidx2']
df4.index.names = ['Ridx1','Ridx2']
df4

DataFrame row 인덱스와 column 인덱스 교환

  • stack() 메서드
    • column 인덱스를 row 인덱스로 변환해 줌
  • unstack() 메서드
    • row 인덱스를 column 인덱스로 변환해 줌
  • level 속성을 사용하여 어느 위치에 추가해 줄지 결정 가능.
df4.stack('Cidx1') # level default값이 -1 이라서 가장 마지막에 추가된다.
df4.stack(0) # 은 위 값과 같은 결과를 가진다.

df4.unstack('Ridx2') # Ridx2가 column에 추가됨.

 

다중 인덱스가 있는 경우의 인덱싱

  • 인덱스 값이 하나의 label이나 숫자가 아니라면 ()로 둘러싸인 튜플이 되어야 한다.
  • loc 인덱서를 사용하는 경우에도 동일하게 튜플을 사용해서 인덱싱 해야 한다.
df3[('B','C1')]

print(df3.loc[0,('B','C1')])
df3.loc[0,('B','C1')]  = 100
df3.loc[0,('B','C1')]

# 단, iloc 인덱서를 사용하는 경우에는 튜플 형태의 다중인덱스를 사용할 수 없다.
print(df3.iloc[0][2])
# 만약 하나의 레벨 값만 넣으면 다중 인덱스 중에서 가장 상위의 값을 지정한 것으로 반환합니다.
df3['A']

DataFrame 다중 인덱스가 있는 경우의 인덱싱

df4

print(df4.loc[:,('A','C1')])
df4.loc[('M','id_1'),('A','C1')]

print(df4.loc[('M','id_1'),:])df4.loc[('All','All'),:] = df4.sum()df4

DataFrame 다중 인덱스가 있는 경우의 인덱싱

  • 다중 인덱스의 튜플 내에서는 콜론(:), 즉 슬라이스 기호를 사용할 수 없고, 대신 slice(None) 값을 사용해야 한다.
print(df4.loc[('M'),:])
df4.loc[('M',slice(None)),:]

다중 인덱스의 인덱스 순서 교환

  • swaplevel(i, j, axis)
  • i, j는 교환하고자 하는 인덱스 label이고,
  • axis는 0일 때 row 인덱스, 1일 때 column인덱스를 뜻한다. default값은 0 임
df6 = df4.swaplevel('Cidx1','Cidx2',1)
df6

df5 = df4.swaplevel('Ridx1','Ridx2')
df5

 

DataFrame 다중 인덱스가 있는 경우의 정렬

  • 다중 인덱스가 있는 DF를 sort_index로 정렬할 때는 level인수를 사용하여
  • 어떤 인덱스를 기준으로 정렬하는지 알려줘야 한다.
print(df5.sort_index(level=0))
df6.sort_index(axis = 1,level = 0)