Pandas Dataframe Performance 应用函数与 shift
Posted
技术标签:
【中文标题】Pandas Dataframe Performance 应用函数与 shift【英文标题】:Pandas Dataframe Performance apply function with shift 【发布时间】:2017-12-29 21:32:04 【问题描述】:我正在尝试优化我的代码。一个电话很快,但因为我经常遇到一些问题。
我的输入数据如下所示:
df = pd.DataFrame(data=np.random.randn(30),
index=pd.date_range(pd.datetime(2016,1,1), periods = 30))
df.iloc[:20] = np.nan
现在我只想应用一个简单的功能。这是我要优化的部分:
s = df >= df.shift(1)
s = s.applymap(lambda x: 1 if x else 0)
现在我有 1000 个循环,最好是 3:每个循环 1.36 毫秒。我想应该可以做得更快。不确定我是否应该矢量化,仅使用 numpy 或使用 cython。任何想法的最佳方法?我对移位运算符有点挣扎。
【问题讨论】:
不需要循环或apply
,只需:(df >= df.shift(1)).dropna().astype(int)
谢谢,获得了 2 倍的改进! 1000 次循环,最好的 3 次:每个循环 776 µs
其实去掉dropna
。你不需要它
【参考方案1】:
您可以将比较结果直接从bool
转换为int
:
(df >= df.shift(1)).astype(int)
【讨论】:
【参考方案2】:@Paul H 的回答很好,很高效,我通常会推荐。
也就是说,如果您想榨取最后一点性能,这是numba
的一个不错的候选者,您可以使用它在一次数据传递中计算答案。
from numba import njit
@njit
def do_calc(arr):
N = arr.shape[0]
ans = np.empty(N, dtype=np.int_)
ans[0] = 0
for i in range(1, N):
ans[i] = 1 if arr[i] > arr[i-1] else 0
return ans
a = (df >= df.shift(1)).astype(int)
b = pd.DataFrame(pd.Series(do_calc(df[0].values), df[0].index))
from pandas.testing import assert_frame_equal
assert_frame_equal(a, b)
这里是时间
In [45]: %timeit b = pd.DataFrame(pd.Series(do_calc(df[0].values), df[0].index))
135 µs ± 1.83 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [46]: %timeit a = (df >= df.shift(1)).astype(int)
762 µs ± 22.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
【讨论】:
这似乎与使用 numpy 数组的解决方案一样快。很有意思。非常感谢您的回答!!【参考方案3】:这是我目前最好的解决方案:
values = df.values[1:] >= df.values[:-1]
data = np.array(values, dtype=int)
s = pd.DataFrame(data, df.index[1:])
我得到了 10000 个循环,最好是 3 个:每个循环 125 µs。 x10 改进。但我认为它可以做得更快。
PS:此解决方案并不完全正确,因为缺少第一个零 / nan。 PPS:可以通过 pd.DataFrame(np.append([[0]],data), df.index) 进行纠正
【讨论】:
“RuntimeWarning:在更大的_equal中遇到无效值”并且输出不匹配。 你是对的,这是一个错误,因为 np.nan 与浮点数进行了比较。 Numpy 将其转换为 false。这很好,但警告仍然不好。 这是一个警告,但输出与这个答案和问题不匹配,所以它不起作用。 你说得对。现在添加了这个解决方案。它有效并且输出匹配。但是有一个警告——不是那么好。但另一方面,这只是一个警告,它仍然有效且安全。以上是关于Pandas Dataframe Performance 应用函数与 shift的主要内容,如果未能解决你的问题,请参考以下文章
pandas.DataFrame.loc好慢,怎么遍历访问DataFrame比较快
将 Pandas Multiindexed DataFrame 与 Singleindexed Pandas DataFrame 合并
pandas.DataFrame.loc好慢,怎么遍历访问DataFrame比较快