728x90
728x170
판다스의 주요 기능
- head 와 tail 메소드를 사용하여 시리즈나 데이터프레임의 내용을 살펴볼 수 있다.
>>> ser = pd.Series(np.random.randn(1000))
>>> ser.head()
0 0.800680
1 -1.002317
2 0.808993
3 0.648255
4 -1.096188
dtype: float64
>>> ser.tail(3)
997 0.905623
998 -0.383506
999 -0.104021
dtype: float64
- 판다스는 메타데이터에 접근하도록 많은 속성을 가지고 있다.
- shape 속성으로 객체의 축 차원을 알 수 있다.
- 축 라벨을 확인하기 위해 시리즈에는 index, 데이터프레임의 행에는 index, 그리고 열에는 columns 속성을 사용할 수 있다.
ind = pd.date_range('1/1/2021', periods=5)
ser = pd.Series(np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])
df = pd.DataFrame(np.random.randn(5, 3), index=ind, columns=['A', 'B', 'C'])
df[:2]
판다스 객체 이진 연산
- 판다스 데이터 구조 사이에 이진 연산을 할 때 고려해야 하는 2가지 사항
- 데이터프레임과 시리즈 객체들 사이에서 연산을 할 때 브로드캐스팅.
- 계산 시 손실 데이터의 처리 방법
- 데이터프레임
- 이진 연산을 위한 add(), sub(), mul(), div() 메소드와 이와 관련된 radd(), rsub() 등의 함수를 갖는다.
- 브로드캐스팅 연산 시에는 주로 시리즈를 입력한다.
- 함수를 적용할 때는 축 키워드에서 지정해 해당 index나 열에 맞게 사용한다.
df = pd.DataFrame({'one' : pd.Series(np.random.randn(2), index=['a', 'b']),
'two' : pd.Series(np.random.randn(3), index=['a', 'b', 'c']),
'three' : pd.Series(np.random.randn(2), index=['b', 'c'])})
df
>>> df.iloc[1]
one 0.653086
two 0.672652
three -2.003373
Name: b, dtype: float64
>>> df['two']
a 0.540905
b 0.672652
c -1.112673
Name: two, dtype: float64
>>> row = df.iloc[1]
>>> col = df['two']
- 이번에는 축의 값을 다르게 하여 sub() 메소드를 적용해본다.
df.sub(row, axis='columns')
더보기
- df 의 열 축을 기준으로 각 열의 값에서 인덱스 b의 값을 빼는 연산이다.
df.sub(col, axis=0)
더보기
- axis=1을 입력해도 axis='columns'와 같은 연산 결과를 얻는다.
- axis=0을 입력하면 axis='index'와 같은 연산 결과를 얻을 수 있다.
- 시리즈와 데이터프레임의 산술 연산 함수들은 매개 변수로 fill_value 옵션을 가진다.
- 이 옵션으로 어떤 위치의 손실 값을 대체할 수 있지만, 최대 1개의 손실 값만을 대체할 수 있다.
d = {'one' : [1., 2., np.nan], 'two' : [3., 2., 1.], 'three' : [np.nan, 1., 1.]}
df = pd.DataFrame(d, index=list('abc'))
df
d1 = {'one' : pd.Series([1., 2.], index=['a', 'b']),
'two' : pd.Series([1., 1., 1.], index=['a', 'b', 'c']),
'three' : pd.Series([2., 2., 2.], index=['a', 'b', 'c'])}
df1 = pd.DataFrame(d1)
df1
- 2개의 데이터프레임 객체를 더할 때, 두 데이터프레임에 손실 값이 있으면 손실 값을 0으로 바꾸어 연산할 수 있다.
- 또한, fillna()를 사용하여 손실 값을 다른 값으로 변환할 수 있다.
df + df1
df.add(df1, fill_value=0)
DataFrame.sub 메소드를 사용하는 연산 예제
df = pd.DataFrame({'angles' : [0, 3, 4], 'degrees' : [360, 180, 360]}, index=['circle', 'triangle', 'rectangle'])
df
df + 1
df - [1, 2] # 연산자를 이용해 리스트 빼기
df.sub([1, 2], axis='columns') # sub() 메소드에서 축을 지정하여 리스트 빼기
df1 = df.sub(pd.Series([1, 2, 3], index=['circle', 'triangle', 'rectangle']), axis='index')
df1
더보기
- df와 시리즈 객체의 인덱스가 동일하므로 서로 뺄셈 연산을 할 수 있다.
요약과 통계 연산
- 시리즈와 데이터프레임에는 요약과 통계 연산을 위한 많은 메소드가 있다.
- 이 메소드들은 ndarray.{sum, std 등}에서 axis 인수를 가지는데, 이 인수는 이름이나 정수 형태로 입력한다.
- 통계 처리를 위한 연산을 할 때는 다음과 같은 손실 데이터 처리 방법을 고려한다.
- 데이터를 더할 때 손실 값(NA)들은 0으로 취급한다.
- 데이터가 모두 NA이면 그 결과는 0이다.
- cumsum()과 cumprod()는 기본으로 손실 값들을 무시하지만 결과 배열에서는 유지한다.
d = {'one' : [1., 2., np.nan], 'two' : [3., 2., 1.], 'three' : [np.nan, 1., 1.]}
df = pd.DataFrame(d, index=list('abc'))
df
>>> df.mean(0)
one 1.5
two 2.0
three 1.0
dtype: float64
>>> df.mean(1)
a 2.000000
b 1.666667
c 1.000000
dtype: float64
- skipna 옵션을 사용하여 손실 데이터를 배제할지 결정할 수 있다.
- 기본값은 True 이다.
>>> df.sum(0, skipna=False)
one NaN
two 6.0
three NaN
dtype: float64
>>> df.sum(1, skipna=True)
a 4.0
b 5.0
c 2.0
dtype: float64
- 브로드캐스팅과 산술 연산을 함께 처리할 수 있으면 '평균이 0, 표준 편차가 1인 정규 분포' 와 같은 다양한 통계 절차를 입력할 수 있다.
>>> df.std()
one 0.707107
two 1.000000
three 0.000000
dtype: float64
>>> df.std(axis=1) # 기본값은 ddof=1
a 1.414214
b 0.577350
c 0.000000
dtype: float64
>>> np.std(df, axis=1) # 기본값은 ddof=0
a 1.000000
b 0.471405
c 0.000000
dtype: float64
>>> np.std(df, ddof=1, axis=1)
a 1.414214
b 0.577350
c 0.000000
dtype: float64
>>> df[['one', 'two', 'three']].std()
one 0.707107
two 1.000000
three 0.000000
dtype: float64
- 누적합을 계산하는 cumsum() 메소드는 다음과 같이 적용할 수 있다.
df.cumsum()
- mean(), std() 및 sum()과 같은 넘파이 함수들은 시리즈 입력값에 있는 손실 값을 기본으로 제외한다.
>>> np.mean(df['one'])
1.5
- Series.nunique() 는 시리즈에서 손실 값을 제외한 유일한 요소의 개수를 반환한다.
>>> ser = pd.Series(np.random.randn(500))
>>> ser[20:500] = np.nan
>>> ser[10:20] = 5
>>> ser.nunique()
11
- describe() 메소드는 데이터프레임의 행이나 시리즈에서 다양한 요약 통계를 계산할 수 있다.
>>> ser = pd.Series(np.random.randn(1000))
>>> ser[::2] = np.nan
>>> ser.describe()
count 500.000000
mean -0.009480
std 1.002857
min -2.859723
25% -0.678066
50% -0.088924
75% 0.722685
max 2.910388
dtype: float64
- 다음은 데이터프레임의 행에 다양한 요약 통계를 계산한다.
df = pd.DataFrame(np.random.randn(1000, 4), columns=['a', 'b', 'c', 'd'])
df.iloc[::2] = np.nan
df.describe()
- 출력에 포함할 특정 백분위수를 선택할 수 있다.
- 확률 통계에서 분위수(Quantile)는 범위나 샘플의 관찰 구간을 같은 확률로 가진 연속 구간으로 나누거나, 동등한 크기의 구간으로 구분하는 지점이다.
- 사분위수(Quantile) 중 2사분위수는 중앙값(Median)이라 한다.
- 확률 통계에서 분위수(Quantile)는 범위나 샘플의 관찰 구간을 같은 확률로 가진 연속 구간으로 나누거나, 동등한 크기의 구간으로 구분하는 지점이다.
>>> ser.describe(percentiles=[0.05, 0.25, .75, .95])
count 500.000000
mean -0.009480
std 1.002857
min -2.859723
5% -1.608900
25% -0.678066
50% -0.088924
75% 0.722685
95% 1.588207
max 2.910388
dtype: float64
- 수치가 아닌 객체에 describe() 메소드를 적용하면 다음 예와 같이 유일 값의 수와 가장 빈번히 발생하는 값들의 간단한 요약을 반환한다.
>>> ser = pd.Series(['a', 'a', 'b', 'c', 'c', np.nan, 'c', 'd'])
>>> ser.describe()
count 7
unique 4
top c
freq 3
dtype: object
- 범주형과 수치가 혼합된 타입의 데이터프레임 객체에 describe() 메소드를 적용하면 수치로 이루어진 열만 반환한다.
df = pd.DataFrame({'a' : ['Yes', 'Yes', 'No', 'No'], 'b' : range(4)})
df.describe()
- describe()에 include와 exclude 인수를 적용할 수 있다.
- exclude 에는 적용하지 않을 열을 전달한다.
df.describe(include=['object'])
df.describe(include=['number'])
df.describe(include='all')
더보기
- 객체 a와 수치 b에 대해 인수 all을 적용하면 객체와 수치 모두를 포함한다.
- idxmax()와 idxmin() 메소드는 시리즈와 데이터프레임의 요소가 최댓값과 최솟값을 가지는 인덱스의 라벨을 계산한다.
- 넘파이의 argmax()와 argmin() 메소드와 동일하다.
>>> ser = pd.Series(np.random.randn(5))
>>> ser
0 -1.658467
1 0.910685
2 2.556914
3 0.242846
4 -0.095138
dtype: float64
>>> ser.idxmin(), ser.idxmax() # 해당 값이 있는 인덱스를 출력한다.
(0, 2)
- idxmax()와 idxmin() 메소드의 축을 인수로 전달하여 실행할 수 있다.
df = pd.DataFrame(np.random.randn(4, 3), columns=['A', 'B', 'C'])
df
>>> df.idxmin(axis=0)
A 1
B 2
C 1
dtype: int64
>>> df.idxmin()
df.idxmin()
df.idxmin()
A 1
B 2
C 1
dtype: int64
>>> df.idxmax(axis=1)
0 C
1 C
2 A
3 B
dtype: object
- 최솟값과 최댓값에 일치하는 행이나 열이 다수라면 idxmin()과 idxmax()는 첫 번째로 일치하는 인덱스를 반환한다.
df1 = pd.DataFrame([2, 1, 1, 3, np.nan], columns=['A'], index=list('edcba'))
df1
>>> df1['A'].idxmin()
'd'
- 시리즈 메소드인 value_counts()는 1차원 배열 값의 도수를 계산한다.
- 이 메소드는 규칙적 배열에 사용할 수 있다.
>>> data = np.random.randint(0, 7, size=30)
>>> data
array([6, 5, 3, 0, 4, 1, 6, 2, 0, 5, 5, 3, 4, 0, 6, 5, 3, 3, 4, 1, 5, 6,
0, 1, 0, 6, 6, 4, 4, 5])
>>> ser1 = pd.Series(data)
>>> ser1.value_counts()
6 6
5 6
0 5
4 5
3 4
1 3
2 1
dtype: int64
>>> pd.value_counts(data)
6 6
5 6
0 5
4 5
3 4
1 3
2 1
dtype: int64
- 함수 cut()과 qcut()을 사용하면 연속하는 값들을 구간(bin)으로 나눌 수 있다.
- 구간은 범주(Category)를 가지는 저장소로 이해할 수 있다.
- cut() 함수
- 데이터 값들을 개별적인 간격으로 나누어 구간으로 분할하거나 순서를 정렬할 때 사용한다.
- 연속적인 값의 변수나 범주형 변수의 범위를 다룰 때 적용할 수 있다.
- 예) 나이를 나이 범위의 그룹으로 변환
>>> pd.cut(np.array([1, 7, 5, 4, 6, 3]), 3)
[(0.994, 3.0], (5.0, 7.0], (3.0, 5.0], (3.0, 5.0], (5.0, 7.0], (0.994, 3.0]]
Categories (3, interval[float64, right]): [(0.994, 3.0] < (3.0, 5.0] < (5.0, 7.0]]
- 인수 retbins=True를 입력하면 구간 값을 반환한다.
>>> pd.cut(np.array([1, 7, 5, 4, 6, 3]), 3, retbins=True) # 구간 값을 반환
([(0.994, 3.0], (5.0, 7.0], (3.0, 5.0], (3.0, 5.0], (5.0, 7.0], (0.994, 3.0]]
Categories (3, interval[float64, right]): [(0.994, 3.0] < (3.0, 5.0] < (5.0, 7.0]],
array([0.994, 3. , 5. , 7. ]))
- 구간에 특정 라벨을 할당하여 labels 범주를 반환할 수 있다.
>>> pd.cut(np.array([1, 7, 5, 4, 6, 3]), 3, labels=['bad', 'medium', 'good'])
['bad', 'good', 'medium', 'medium', 'good', 'bad']
Categories (3, object): ['bad' < 'medium' < 'good']
- labels=False 인수를 입력하면 범주형 시리즈나 정수 배열을 반환한다.
>>> pd.cut([0, 1, 1, 2], bins=4, labels=False)
array([0, 1, 1, 3], dtype=int64)
- cut() 함수에 시리즈를 입력하면 categorical dtype인 시리즈를 반환한다.
>>> ser = pd.Series(np.array([2, 4, 6, 8, 10]), index=['a', 'b', 'c', 'd', 'e'])
>>> pd.cut(ser, 3)
a (1.992, 4.667]
b (1.992, 4.667]
c (4.667, 7.333]
d (7.333, 10.0]
e (7.333, 10.0]
dtype: category
Categories (3, interval[float64, right]): [(1.992, 4.667] < (4.667, 7.333] < (7.333, 10.0]]
- qcut() 함수
- 분위(Quantile) 기반의 이산(Discretization) 함수
- 순위나 샘플 분위에 기반하여 변수를 동등한 크기로 나눈다.
- 범위 밖의 값들은 결과인 범주형 객체에서 NA가 된다.
>>> pd.qcut(range(5), 4)
[(-0.001, 1.0], (-0.001, 1.0], (1.0, 2.0], (2.0, 3.0], (3.0, 4.0]]
Categories (4, interval[float64, right]): [(-0.001, 1.0] < (1.0, 2.0] < (2.0, 3.0] < (3.0, 4.0]]
>>> pd.qcut(range(5), 3, labels=['good', 'medium', 'bad'])
['good', 'good', 'medium', 'bad', 'bad']
Categories (3, object): ['good' < 'medium' < 'bad']
>>> pd.qcut(range(5), 4, labels=False)
array([0, 0, 1, 2, 3], dtype=int64)
- 다음을 통해 cut() 함수와 qcut() 함수의 차이를 확인할 수 있다.
- cut() 함수는 구간 범위에 해당하는 길이가 동등하도록 나눈다.
- qcut() 함수는 구간 범위에 해당하는 개수가 동등하도록 나눈다.
>>> pd.cut(np.random.randn(25), 5).value_counts()
(-2.237, -1.4] 3
(-1.4, -0.567] 5
(-0.567, 0.266] 9
(0.266, 1.098] 6
(1.098, 1.931] 2
dtype: int64
>>> pd.qcut(np.random.randn(25), 5).value_counts()
(-2.13, -1.146] 5
(-1.146, -0.625] 5
(-0.625, 0.123] 5
(0.123, 0.817] 5
(0.817, 2.108] 5
dtype: int64
함수 적용
- 사용자 정의 함수나 다른 라이브러리에 속한 함수들을 판다스 객체에 적용할 때, 이 함수들은 다음과 같이 행, 열 또는 요소 단위의 데이터프레임이나 시리즈에 적용된다.
- 테이블 형태의 함수를 적용 : pipe()
- 행 또는 열 단위의 함수를 적용 : apply()
- Aggregation API : agg()와 transform()
- 요소 단위로 함수를 적용 : applymap()
테이블 형태의 함수 적용
- 테이블 형태의 함수를 적용할 때는 데이터프레임이나 시리즈에 함수로 입력할 수 있다.
- 함수를 체인(Chain) 형태로 호출해야 한다면 pipe() 메소드를 사용할 수 있다.
- 시리즈나 데이터프레임, GroupBy 객체들을 여러 함수와 함께 연쇄적으로 묶을 때 .pipe를 사용한다.
# f(g(h(df), arg1=a), arg2=b, arg3=c)와 같이 사용하는 대신 다음과 같은 로직으로 작성한다.
(df.pipe(h)
.pipe(g, arg1=a)
.pipe(f, arg2=b, arg3=c)
)
- 데이터에 pipe() 메소드를 이용해 사칙 연산을 수행할 수 있다.
data = pd.DataFrame([[1, 1, 1,], [2, 2, 2,], [3, 3, 3]], index=['A', 'B', 'C'], columns=['one', 'two', 'three'])
data
- 생성된 data 객체에 사용자 정의 함수를 사용한 사칙 연산을 pipe() 메소드를 이용해 체인 형태로 묶어 실행한다.
def add(data, arg1):
data1 = data + arg1
return data1
def div(data1, arg2):
data2 = data1 / arg2
return data2
def mul(data2, arg3):
data3 = data2 * arg3
return data3
def sub(data3, arg4):
data4 = data3 - arg4
return data4
(data.pipe(add, arg1=2) # data에 2를 더하기
.pipe(div, arg2=3) # data에 2를 더한 결과에 3으로 나누기
.pipe(mul, arg3=5) # 위 결과를 3으로 나눈 후 5를 곱하기
.pipe(sub, arg4=1)) # 위 결과에서 1을 빼기
예제 : 가족 구성원들의 성별에 따라 평균 나이 구하기
df = pd.DataFrame()
df['name'] = ['jsun', 'jin', 'ujung', 'naeun', 'suho']
df['sex'] = ['female', 'male', 'female', 'female', 'male']
df['age'] = [84, 58, 53, 27, 18]
df
- 데이터를 성별인 sex로 그룹화하고, 각 성별 그룹의 평균 나이를 연산하는 함수를 구성한다.
- 또한, 모든 열 라벨을 대문자로 바꾼 후 데이터프레임 열에 동적 할당한다.
def mean_age_group(dataframe, col):
return dataframe.groupby(col).mean()
def cap_column(dataframe):
dataframe.columns = dataframe.columns.str.upper()
return dataframe
(df.pipe(mean_age_group, col='sex')
.pipe(cap_column))
- 이처럼 pipe()는 여러 연산을 담당하는 다수의 함수를 순차적으로 연계해 처리함으로써 복잡한 연산 과정을 단순화하는 유용한 메소드이다.
행 또는 열 단위의 함수 적용
- apply() 메소드는 axis 인수를 선택적으로 취하므로 이 메소드를 사용하면 데이터프레임의 행 또는 열에 함수를 적용할 수 있다.
data = [{'one' : 1.0, 'two' : 1.2}, {'one' : 0.5, 'two' : 1.1, 'three' : 0.7},
{'one' : 0.7, 'two' : 0.9, 'three' : -1.6}, {'two' : 1.4, 'three' : -1.2}]
df = pd.DataFrame(data, index=list('abcd'))
df
더보기
- df는 딕셔너리형 데이터로 구성된 리스트에서 데이터프레임 객체를 생성한다.
- 앞 결과에 apply() 메소드를 사용해 np.mean을 적용하면 기본으로 열을 중심으로 평균값을 구한다.
- 인수 axis=1을 설정하면 행을 기준으로 연산한다.
>>> df.apply(np.mean)
one 0.733333
two 1.150000
three -0.700000
dtype: float64
>>> df.apply(np.mean, axis=1)
a 1.100000
b 0.766667
c 0.000000
d 0.100000
dtype: float64
- df에 apply() 메소드로 람다 함수를 적용하여 최댓값과 최솟값의 차이를 구할 수 있다.
>>> df.apply(lambda x: x.max() - x.min())
one 0.5
two 0.5
three 2.3
dtype: float64
df.apply(np.cumsum)
df.apply(np.exp)
- apply() 메소드에는 다음과 같이 문자열인 메소드 이름을 적용할 수도 있다.
>>> df.apply('mean')
one 0.733333
two 1.150000
three -0.700000
dtype: float64
>>> df.apply('mean', axis=1)
a 1.100000
b 0.766667
c 0.000000
d 0.100000
dtype: float64
Aggregation API 함수 적용
- Aggregaton API
- 다중 종합 연산을 수행할 수 있도록 도와준다.
- agg() 메소드
- aggregation()의 약칭
- 데이터프레임과 시리즈에 적용 가능할 수 있다.
- 명시한 축에 1개 이상의 연산을 통합하여 실행하며, 반환된 객체의 차원이 축소된다.
- transform() 메소드
- 원형과 같은 크기의 Index 객체를 반환한다.
- 하나보다는 여러 연산을 동시에 수행하도록 하며, Aggregation API와 유사하게 동작한다.
- agg()로 행에 여러 함수를 종합하여 연산하기 위해 다음과 같이 df 객체를 생성한다.
df = pd.DataFrame([[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[np.nan, np.nan, np.nan]], columns=['A', 'B', 'C'])
df
df.agg(['sum', 'min'])
- 메소드 agg()에 축을 명시하지 않으면 각 열에 각기 다른 종합 연산을 실행한다.
- axis='columns'인 경우 행의 평균을 구한다.
df.agg({'A' : ['sum', 'min'], 'B' : ['min', 'max']})
>>> df.agg("mean", axis="columns")
0 2.0
1 5.0
2 8.0
3 NaN
dtype: float64
- Aggregation API를 사용해 종합 연산을 수행하기 위해 다음과 같이 데이터프레임을 생성한다.
adf = pd.DataFrame(np.random.randn(6, 3), columns=['A','B','C'], index=pd.date_range('7/1/2021', periods=6))
adf.iloc[2:4] = np.nan
adf
- 단일 함수를 사용하는 방법은 apply() 메소드를 사용하는 방법과 동일하다.
- 또한, 문자열인 메소드 이름을 전달할 수도 있다.
- 이 연산들은 시리즈를 반환한다.
>>> adf.agg(np.sum)
A -0.080577
B -0.528719
C -1.367696
dtype: float64
>>> adf.agg('sum')
A -0.080577
B -0.528719
C -1.367696
dtype: float64
>>> adf.sum()
A -0.080577
B -0.528719
C -1.367696
dtype: float64
- 시리즈에 단일 종합 연산을 실행하면 스칼라 값을 반환한다.
>>> adf.A.agg('sum')
-0.08057672273092953
- 복수의 함수로 종합 연산을 실행할 때 여러 인수를 리스트로 전달할 수 있다.
- 전달한 함수는 연산 결과에서 데이터프레임의 행으로 나타난다.
adf.agg(['sum'])
- 복수의 함수를 사용하면 복수의 행을 반환한다.
adf.agg(['sum', 'mean'])
- 람다 함수를 입력하면 <lambda> 이름의 행을 반환한다.
>>> adf.A.agg(['sum', lambda x: x.mean()])
sum -0.080577
<lambda> -0.020144
Name: A, dtype: float64
- 사용자 정의 함수를 입력하면 행에 그 함수의 이름을 반환한다.
def mymean(x):
return x.mean()
>>> adf.A.agg(['sum', mymean])
sum -0.080577
mymean -0.020144
Name: A, dtype: float64
- DataFrame.agg()로 각 열에 함수 이름을 딕셔너리형으로 전달하면 각 열에 해당 함수를 적용한다.
>>> adf.agg({'A': 'mean', 'B': 'sum'})
A -0.020144
B -0.528719
dtype: float64
- 열 라벨에 유사 리스트로 함수를 전달하면 데이터프레임 형태로 출력된다.
adf.agg({'A': ['mean', 'min'], 'B': 'sum'})
- transform() 메소드를 사용하면 데이터프레임에 람다 함수를 적용하여 연산할 수 있다.
df = pd.DataFrame({'A': range(3), 'B': range(1, 4)})
df
df.transform(lambda x: x + 1)
- transform() 메소드에는 넘파이 함수, 문자열인 함수 이름 또는 사용자 정의 함수를 입력할 수 있으며, 전체 프레임을 반환한다.
adf.transform(np.abs)
더보기
- np.abs 대신 abs 또는 lambda x: x.abs()를 입력해도 결과는 같다.
- np.abs(adf)의 연산 결과와도 동일하다.
- 시리즈에 함수 하나를 입력하면 단일 시리즈를 반환한다.
>>> adf.A.transform(np.abs)
2021-07-01 0.118335
2021-07-02 1.011351
2021-07-03 NaN
2021-07-04 NaN
2021-07-05 0.238513
2021-07-06 0.971750
Freq: D, Name: A, dtype: float64
- 복수의 함수를 전달하면 멀티 인덱스를 가진 열로 이루어진 데이터프레임을 반환한다.
- 첫 번째 레벨 : 원래 데이터프레임의 열 이름
- 두 번째 레벨 : 변환하는 함수들의 이름
adf.transform([np.abs, lambda x: x + 1])
- 복수의 함수를 시리즈로 입력하면 데이터프레임을 반환한다.
- 결과의 열 이름은 변환 함수의 이름이다.
adf.A.transform([np.abs, lambda x: x + 1])
- 함수들로 이루어진 딕셔너리를 전달하면 각 열마다 연산을 적용할 수 있다.
adf.transform({'A': np.abs, 'B': lambda x: x + 1})
- 리스트가 있는 딕셔너리를 전달하면 각 열에 함수를 호출하여 연산을 실행하여 멀티 인덱스를 가진 데이터프레임을 생성한다.
adf.transform({'A': np.abs, 'B': [lambda x: x + 1, 'sqrt']})
요소 단위로 함수들을 적용
- 데이터프레임에 applymap() 메소드로 사용자 정의 함수를 적용할 수 있다.
- 시리즈에 사용자 정의 함수를 적용하려면 map() 메소드를 사용한다.
- 사용자 정의 함수에는 단일 값을 입력하고 반환한다.
- apply() 메소드는 데이터프레임과 시리즈에 모두 적용할 수 있다.
- apply() 메소드는 요소별로 함수를 적용한다.
- applymap()와 apply() 메소드는 호출할 수 있는 사용자 정의 함수만 인수로 가질 수 있다.
- map() 메소드는 딕셔너리, 시리즈, 사용자 정의 함수를 인자로 가질 수 있다.
예제 : 데이터프레임에 람다 함수를 인수로 갖는 applymap() 메소드 적용하기
df = pd.DataFrame([[1, 2.12], [3.356, 4.567]])
df
df.applymap(lambda x: len(str(x)))
- 다음과 같이 df에 람다 함수를 적용하거나 제곱 연산을 수행할 수 있다.
df.applymap(lambda x: x**2)
df ** 2
- 인수가 딕셔너리형일 때, 딕셔너리 내에 키로써 존재하지 않는 시리즈 값들은 NaN으로 변환된다.
>>> ser = pd.Series(['cat', 'dog', np.nan, 'rabbit']) # ser 객체 생성
>>> ser
0 cat
1 dog
2 NaN
3 rabbit
dtype: object
- map() 메소드에는 딕셔너리, 시리즈, 사용자 정의 함수를 사용할 수 있다.
- 딕셔너리에 존재하지 않는 값들은 NaN으로 변환된다.
>>> ser.map({'cat': 'kitten', 'dog': 'puppy'})
0 kitten
1 puppy
2 NaN
3 NaN
dtype: object
- map() 메소드에 사용자 정의 함수를 인수로 사용할 수 있다.
>>> ser.map('I am a {}'.format)
0 I am a cat
1 I am a dog
2 I am a nan
3 I am a rabbit
dtype: object
- 손실 값에 함수를 적용하지 않고 NaN 값을 유지하려면 다음과 같이 na_action='ignore'을 입력한다.
>>> ser.map('I am a {}'.format, na_action='ignore')
0 I am a cat
1 I am a dog
2 NaN
3 I am a rabbit
dtype: object
728x90
그리드형(광고전용)
'In-depth Study > Pandas' 카테고리의 다른 글
[Pandas] 수학 계산 (0) | 2022.05.31 |
---|---|
[Pandas] 데이터의 그룹 연산 (0) | 2022.05.30 |
[Pandas] 데이터 가공 (0) | 2022.05.29 |
[Pandas] 데이터 타입과 입출력 (0) | 2022.05.27 |
[Pandas] 데이터 처리 (0) | 2022.05.27 |
[Pandas] 판다스 데이터 구조 (1) | 2022.05.24 |
[Pandas] 판다스(Pandas) 개요 (0) | 2022.05.24 |