增长数据框的 Pandastic 方式
Pandastic way of growing a dataframe
所以,我有一个按年索引的数据框,我想在结束年份(2013 年)之后增加一些逻辑,比如,将最后一个值增加 n 个百分点,持续 10 年,但逻辑也可以是只需添加一个常量或略微增长的数字。我会把它留给一个函数,然后把逻辑塞在那里。
我想不出一种简洁的矢量化方法来用任意长度的时间和逻辑来做到这一点,留下更长的数据帧并添加额外的增量,并且不想循环它。
具体的计算很重要。通常,您必须在循环中计算值。然而,一些 NumPy ufunc(例如 np.add
、np.multiply
、np.minimum
、np.maximum
)有一个 accumulate
method,这可能对计算有用。
例如,要计算给定恒定增长率的值,您可以使用 np.multiply.accumulate
(或 cumprod
):
import numpy as np
import pandas as pd
N = 10
index = pd.date_range(end='2013-12-31', periods=N, freq='D')
df = pd.DataFrame({'val':np.arange(N)}, index=index)
last = df['val'][-1]
# val
# 2013-12-22 0
# 2013-12-23 1
# 2013-12-24 2
# 2013-12-25 3
# 2013-12-26 4
# 2013-12-27 5
# 2013-12-28 6
# 2013-12-29 7
# 2013-12-30 8
# 2013-12-31 9
# expand df
index = pd.date_range(start='2014-1-1', periods=N, freq='D')
df = df.reindex(df.index.union(index))
# compute new values
rate = 1.1
df['val'][-N:] = last*np.multiply.accumulate(np.full(N, fill_value=rate))
产量
val
2013-12-22 0.000000
2013-12-23 1.000000
2013-12-24 2.000000
2013-12-25 3.000000
2013-12-26 4.000000
2013-12-27 5.000000
2013-12-28 6.000000
2013-12-29 7.000000
2013-12-30 8.000000
2013-12-31 9.000000
2014-01-01 9.900000
2014-01-02 10.890000
2014-01-03 11.979000
2014-01-04 13.176900
2014-01-05 14.494590
2014-01-06 15.944049
2014-01-07 17.538454
2014-01-08 19.292299
2014-01-09 21.221529
2014-01-10 23.343682
要增加一个常数值,您可以简单地使用 np.arange
:
step=2
df['val'][-N:] = np.arange(last+step, last+(N+1)*step, step)
或cumsum
:
step=2
df['val'][-N:] = last + np.full(N, fill_value=step).cumsum()
一些线性递推关系可以用scipy.signal.lfilter表示。参见例如,
Trying to vectorize iterative calculation with numpy and Recursive definitions in Pandas
所以,我有一个按年索引的数据框,我想在结束年份(2013 年)之后增加一些逻辑,比如,将最后一个值增加 n 个百分点,持续 10 年,但逻辑也可以是只需添加一个常量或略微增长的数字。我会把它留给一个函数,然后把逻辑塞在那里。
我想不出一种简洁的矢量化方法来用任意长度的时间和逻辑来做到这一点,留下更长的数据帧并添加额外的增量,并且不想循环它。
具体的计算很重要。通常,您必须在循环中计算值。然而,一些 NumPy ufunc(例如 np.add
、np.multiply
、np.minimum
、np.maximum
)有一个 accumulate
method,这可能对计算有用。
例如,要计算给定恒定增长率的值,您可以使用 np.multiply.accumulate
(或 cumprod
):
import numpy as np
import pandas as pd
N = 10
index = pd.date_range(end='2013-12-31', periods=N, freq='D')
df = pd.DataFrame({'val':np.arange(N)}, index=index)
last = df['val'][-1]
# val
# 2013-12-22 0
# 2013-12-23 1
# 2013-12-24 2
# 2013-12-25 3
# 2013-12-26 4
# 2013-12-27 5
# 2013-12-28 6
# 2013-12-29 7
# 2013-12-30 8
# 2013-12-31 9
# expand df
index = pd.date_range(start='2014-1-1', periods=N, freq='D')
df = df.reindex(df.index.union(index))
# compute new values
rate = 1.1
df['val'][-N:] = last*np.multiply.accumulate(np.full(N, fill_value=rate))
产量
val
2013-12-22 0.000000
2013-12-23 1.000000
2013-12-24 2.000000
2013-12-25 3.000000
2013-12-26 4.000000
2013-12-27 5.000000
2013-12-28 6.000000
2013-12-29 7.000000
2013-12-30 8.000000
2013-12-31 9.000000
2014-01-01 9.900000
2014-01-02 10.890000
2014-01-03 11.979000
2014-01-04 13.176900
2014-01-05 14.494590
2014-01-06 15.944049
2014-01-07 17.538454
2014-01-08 19.292299
2014-01-09 21.221529
2014-01-10 23.343682
要增加一个常数值,您可以简单地使用 np.arange
:
step=2
df['val'][-N:] = np.arange(last+step, last+(N+1)*step, step)
或cumsum
:
step=2
df['val'][-N:] = last + np.full(N, fill_value=step).cumsum()
一些线性递推关系可以用scipy.signal.lfilter表示。参见例如, Trying to vectorize iterative calculation with numpy and Recursive definitions in Pandas