[Pandas] Pandas 활용

Pandas 활용

Pandas 에서 제공하는 다양한 기능들을 알아보려고 한다. 내용이 복잡하지 않아 간단한 설명과 Code 만을 삽입했다.

조건으로 검색하기

NumPy 배열과 마찬가지로 Masking 연산이 가능하다.

import numpy as np
import pandas as pd

df = pd.DataFrame(np.random.rand(5, 2), columns=["A", "B"])
df["A"] < 0.5

# 0    False
# 1    False
# 2    False
# 3    False
# 4     True
# Name: A, dtype: bool

앞선 Pandas 기초를 다룬 게시글에서 Series 데이터에 masking 된 Series 타입을 인덱스로 넣어주면 데이터를 추출하는 모습을 볼 수 있었다. 여기서도 같은 방법으로 데이터를 추출할 수 이다.

import numpy as np
import pandas as pd

df = pd.DataFrame(np.random.rand(5, 2), columns=["A", "B"])
df[(df["A"] < 0.5) & (df["B"] > 0.3)] # df.query("A < 0.5 and B > 0.3")

#           A         B
# 2  0.091172  0.944648
# 3  0.337452  0.431645

원소가 문자열이라면 .query 명령어가 아니라 contains 또는 match 를 사용해 행을 추출할 수 있다.

df['Animal'].str.contains("Cat")
df.Animal.str.match("Cat")

함수로 데이터 처리하기

apply 를 통해 각 데이터에 함수를 적용할 수 있다.

df = pd.DataFrame(np.arange(5), columns=["Num"])

def square(x):
    return x**2

df["Square"] = df["Num"].apply(square)
df["Multiplication"] = df.Num.apply(lambda x: x * 2)

print(df)

#    Num  Square  Multiplication
# 0    0       0               0
# 1    1       1               2
# 2    2       4               4
# 3    3       9               6
# 4    4      16               8

replace 를 이용하면 데이터 값만 대체할 수 있다. 매개변수로는 기존 Data : 바꿀 Data 쌍을 전달하여 대체한다.

df.Num.replace({0: 1, 
                1: 2, 
                2: 3, 
                3: 4,
                4: 5})


# AS-IS
#    Num 
# 0    0
# 1    1
# 2    2
# 3    3
# 4    4

# TO-BE
# 0    1
# 1    2
# 2    3
# 3    4
# 4    5
# Name: Num, dtype: int32

그룹으로 묶기

DataFrame 은 그룹으로 묶어 집계를 수행할 수 있는 groupby 함수를 제공한다.

groupby

groupby 는 간단한 집계를 넘어 조건부로 집계하고 싶은 경우 사용한다. 특정 컬럼을 기준으로 같은 값을 가진 행들을 묶은 뒤, 하나의 데이터로 집계한다. 예를들면, 17번 학생 의 기록을 모두 모은 뒤 합 또는 평균을 구할 수도 있고, 단순히 그 숫자를 카운트 할 수 있다.

df= pd.DataFrame({'key': ['A', 'B', 'C', 'A', 'B', 'C'],
                  'data1': [1,2,3,1,2,3], 
                  'data2':np.random.randint(0, 6, 6)})
#   key  data1  data2
# 0   A      1      3
# 1   B      2      4
# 2   C      3      4
# 3   A      1      0
# 4   B      2      1
# 5   C      3      3

df.groupby('key')
# <pandas.core.groupby.generic.DataFrameGroupBy object at 0x0000025EBF436CD0>

df.groupby('key').sum()
#      data1  data2
# key              
# A        2      3
# B        4      5
# C        6      7

df.groupby(['key','data1']).sum()
#            data2
# key data1       
# A   1          3
# B   2          5
# C   3          7

aggregate

여기에 aggregate 함수를 사용하면 groupby 를 통해 묶은 데이터 모두에 한 번에 집계 함수를 적용할 수 있다. 마치 apply 와 같은 역할이라고 생각하면 된다. 단순히 적용하고픈 연산만 기재할 경우에는 각 열에 연산을 적용한다. 이와 달리, 딕셔너리 형태로 적용하고자 하는 컬럼을 지정한 후 집계 함수를 전달하는 방법도 가능하다.

df
#   key  data1  data2
# 0   A      1      3
# 1   B      2      4
# 2   C      3      4
# 3   A      1      0
# 4   B      2      1
# 5   C      3      3

df.groupby('key').aggregate(['min', np.median, max])
#     data1            data2           
#       min median max   min median max
# key                                  
# A       1    1.0   1     0    1.5   3
# B       2    2.0   2     1    2.5   4
# C       3    3.0   3     3    3.5   4

df.groupby('key').aggregate({'data1': 'min', 'data2': np.sum})
#      data1  data2
# key              
# A        1      3
# B        2      5
# C        3      7

filter

groupby 를 통해 묶은 속성을 기준으로 데이터를 필터링 할 수 있다. 이 때, groupby 로 묶였던 데이터는 다시 풀린다. 아래 예에서 filter 가 적용된 데이터 프레임의 index 가 2와 5로 남아있는 것을 보면 알 수 있다.

def filter_by_mean(x):
    return x['data2'].mean() > 3

df
#   key  data1  data2
# 0   A      1      3
# 1   B      2      4
# 2   C      3      4
# 3   A      1      0
# 4   B      2      1
# 5   C      3      3

df.groupby('key').mean()
#      data1  data2
# key              
# A      1.0    1.5
# B      2.0    2.5
# C      3.0    3.5

df.groupby('key').filter(filter_by_mean)
#   key  data1  data2
# 2   C      3      4
# 5   C      3      3

get_group

groupby 로 묶인 데이터에서 특정 키 값을 가지는 데이터를 가져올 수 있다. 아래와 같이 시도 컬러에 충남 이 적혀있는 그룹만 추출할 수 있다.

df.groupby("시도").get_group("충남")

Multi-Index

DataFrame 은 이는 행 인덱스와 열 인덱스 모두에 계층적 인덱싱 생성을 지원한다. 이렇게 생성된 DataFrame 데이터 접근은 다차원 배열에 접근하는 방식과 유사한 다중 인덱싱 방법이나 계층적 loc, iloc 로 가능하다.

df = pd.DataFrame(
    np.random.randn(4, 2), 
    index=[['A', 'A', 'B', 'B'], ['a', 'b', 'a', 'b']],
    columns=['data1', 'data2']
)

df

#         data1     data2
# A a -0.944477  0.792811
#   b -1.218970  2.140619
# B a -0.651010 -2.472553
#   b -0.579576 -0.774814

df = pd.DataFrame(
    np.random.randn(4, 4),
    columns=[["A", "A", "B", "B"], ["a", "b", "a", "b"]]
)

df

#           A                   B          
#           a         b         a         b
# 0  2.305516  0.580659 -0.695731  0.483767
# 1 -0.645042 -0.779479 -0.217233 -0.807245
# 2 -1.757520  0.587017  0.806789 -0.662921
# 3  1.005211 -1.237330 -0.180914 -0.111120

pivot_table

데이터에서 필요한 자료만 뽑아 새롭게 요약, 분석할 수 있는 기능으로 엑셀의 피봇 데이블과 같다.

  • Index: 행 인덱스로 들어갈 Key
  • Columns: 열 인덱스로 라벨링 될 값
  • Value: 분석할 데이터

예를들어, 타이타닉 데이터에서 성별과 좌석별 생존률을 구하기 위해 아래와 같이 사용할 수 있다.

import seaborn as sns
import pandas as pd

df = sns.load_dataset('titanic')
df.pivot_table(
    index='sex', columns='class', values='survived',
    aggfunc=np.mean
)

# class      First    Second     Third
# sex                                 
# female  0.968085  0.921053  0.500000
# male    0.368852  0.157407  0.135447

df.pivot_table(
    index='sex', columns='class', values=['survived', 'age'],
    aggfunc=np.mean
)

#               age                        survived                    
# class       First     Second      Third     First    Second     Third
# sex                                                                  
# female  34.611765  28.722973  21.750000  0.968085  0.921053  0.500000
# male    41.281386  30.740707  26.507589  0.368852  0.157407  0.135447

Updated:

Leave a comment