적용에서 이전 값도 계산 될 때 Pandas에서 dataframe.apply의 이전 행 값을 사용하는 방법이 있습니까?
다음 데이터 프레임이 있습니다.
Index_Date A B C D
===============================
2015-01-31 10 10 Nan 10
2015-02-01 2 3 Nan 22
2015-02-02 10 60 Nan 280
2015-02-03 10 100 Nan 250
필요 :
Index_Date A B C D
===============================
2015-01-31 10 10 10 10
2015-02-01 2 3 23 22
2015-02-02 10 60 290 280
2015-02-03 10 100 3000 250
Column C
대해 유도된다 2015-01-31
취하여 value
들 D
.
그럼 난 사용해야 value
의를 C
위한 2015-01-31
과 곱셈에 의해 value
의 A
에 2015-02-01
추가합니다 B
.
나는 시도 apply
했고를 shift
사용하면 if else
키 오류가 발생합니다.
먼저 파생 된 값을 만듭니다.
df.loc[0, 'C'] = df.loc[0, 'D']
그런 다음 나머지 행을 반복하고 계산 된 값을 채 웁니다.
for i in range(1, len(df)):
df.loc[i, 'C'] = df.loc[i-1, 'C'] * df.loc[i, 'A'] + df.loc[i, 'B']
Index_Date A B C D
0 2015-01-31 10 10 10 10
1 2015-02-01 2 3 23 22
2 2015-02-02 10 60 290 280
숫자 열이 주어지면 :
lst = []
cols = ['A']
for a in range(100, 105):
lst.append([a])
df = pd.DataFrame(lst, columns=cols, index=range(5))
df
A
0 100
1 101
2 102
3 103
4 104
shift를 사용하여 이전 행을 참조 할 수 있습니다.
df['Change'] = df.A - df.A.shift(1)
df
A Change
0 100 NaN
1 101 1.0
2 102 1.0
3 103 1.0
4 104 1.0
numpy 배열에 재귀 함수를 적용하는 것이 현재 답변보다 빠릅니다.
df = pd.DataFrame(np.repeat(np.arange(2, 6),3).reshape(4,3), columns=['A', 'B', 'D'])
new = [df.D.values[0]]
for i in range(1, len(df.index)):
new.append(new[i-1]*df.A.values[i]+df.B.values[i])
df['C'] = new
산출
A B D C
0 1 1 1 1
1 2 2 2 4
2 3 3 3 15
3 4 4 4 64
4 5 5 5 325
numba
벡터화 할 수없는 재귀 계산의 경우 numba
JIT 컴파일을 사용하고 하위 수준 개체와 함께 작동하는은 종종 성능이 크게 향상됩니다. 일반 for
루프를 정의 하고 데코레이터 @njit
또는 (이전 버전의 경우) 사용하기 만하면됩니다 @jit(nopython=True)
.
합리적인 크기의 데이터 프레임의 경우 일반 for
루프에 비해 ~ 30 배의 성능 향상을 제공합니다 .
from numba import jit
@jit(nopython=True)
def calculator_nb(a, b, d):
res = np.empty(d.shape)
res[0] = d[0]
for i in range(1, res.shape[0]):
res[i] = res[i-1] * a[i] + b[i]
return res
df['C'] = calculator_nb(*df[list('ABD')].values.T)
n = 10**5
df = pd.concat([df]*n, ignore_index=True)
# benchmarking on Python 3.6.0, Pandas 0.19.2, NumPy 1.11.3, Numba 0.30.1
# calculator() is same as calculator_nb() but without @jit decorator
%timeit calculator_nb(*df[list('ABD')].values.T) # 14.1 ms per loop
%timeit calculator(*df[list('ABD')].values.T) # 444 ms per loop
이 질문을 한 지 오래되었지만 누군가에게 도움이되기를 바라면서 답변을 게시하겠습니다.
면책 조항 : 이 솔루션이 표준 이 아니라는 것을 알고 있지만 잘 작동한다고 생각합니다.
import pandas as pd
import numpy as np
data = np.array([[10, 2, 10, 10],
[10, 3, 60, 100],
[np.nan] * 4,
[10, 22, 280, 250]]).T
idx = pd.date_range('20150131', end='20150203')
df = pd.DataFrame(data=data, columns=list('ABCD'), index=idx)
df
A B C D
=================================
2015-01-31 10 10 NaN 10
2015-02-01 2 3 NaN 22
2015-02-02 10 60 NaN 280
2015-02-03 10 100 NaN 250
def calculate(mul, add):
global value
value = value * mul + add
return value
value = df.loc['2015-01-31', 'D']
df.loc['2015-01-31', 'C'] = value
df.loc['2015-02-01':, 'C'] = df.loc['2015-02-01':].apply(lambda row: calculate(*row[['A', 'B']]), axis=1)
df
A B C D
=================================
2015-01-31 10 10 10 10
2015-02-01 2 3 23 22
2015-02-02 10 60 290 280
2015-02-03 10 100 3000 250
그래서 기본적으로 우리는 apply
from pandas와 이전에 계산 된 값을 추적하는 전역 변수의 도움을 사용합니다.
for
루프를 사용한 시간 비교 :
data = np.random.random(size=(1000, 4))
idx = pd.date_range('20150131', end='20171026')
df = pd.DataFrame(data=data, columns=list('ABCD'), index=idx)
df.C = np.nan
df.loc['2015-01-31', 'C'] = df.loc['2015-01-31', 'D']
%%timeit
for i in df.loc['2015-02-01':].index.date:
df.loc[i, 'C'] = df.loc[(i - pd.DateOffset(days=1)).date(), 'C'] * df.loc[i, 'A'] + df.loc[i, 'B']
3.2 s ± 114 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
data = np.random.random(size=(1000, 4))
idx = pd.date_range('20150131', end='20171026')
df = pd.DataFrame(data=data, columns=list('ABCD'), index=idx)
df.C = np.nan
def calculate(mul, add):
global value
value = value * mul + add
return value
value = df.loc['2015-01-31', 'D']
df.loc['2015-01-31', 'C'] = value
%%timeit
df.loc['2015-02-01':, 'C'] = df.loc['2015-02-01':].apply(lambda row: calculate(*row[['A', 'B']]), axis=1)
1.82 s ± 64.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
So 0.57 times faster on average.
I have found the for
-based solution too slow.
df['C'] = 0
df.loc[df.index[1:], 'C'] = df.loc[df.index[:-1], 'D'].to_numpy()
df['C'] = df['D'] * df['A'] + df['B']
Hundreds of times faster. It matters when you have 100+k rows.
ReferenceURL : https://stackoverflow.com/questions/34855859/is-there-a-way-in-pandas-to-use-previous-row-value-in-dataframe-apply-when-previ
'programing' 카테고리의 다른 글
오프라인 / 온라인 데이터 동기화 설계 (Javascript) (0) | 2021.01.16 |
---|---|
인수가없는 생성자가있는 객체를 std :: map에 배치하는 방법은 무엇입니까? (0) | 2021.01.15 |
Uber Android와 같이지도에서 마커 회전 및 애니메이션 이동 (0) | 2021.01.15 |
C ++, C로 Android 프로그래밍을 할 수 있습니까? (0) | 2021.01.15 |
세션 변수에 대한 제한이 있습니까? (0) | 2021.01.15 |