Python 使用Pandas dataframe(列操作)提高我的代码的性能
我正在学习Pandas dataframe和一个与性能优化相关的问题。由于我的速度慢,而且是新手,所以我的代码似乎编写不正确,即使输出是正确的,但性能也很差 问题:我有0和1的位模式。我必须找到1的步幅(为我的分析计算contiguos 1)。我的数据帧是200000列x200行。现在速度非常慢,正在寻找一种更好的方法来完成完整的解决方案,或者用向量操作替换所有列的“for-loop”。例如:Python 使用Pandas dataframe(列操作)提高我的代码的性能,python,pandas,dataframe,bigdata,Python,Pandas,Dataframe,Bigdata,我正在学习Pandas dataframe和一个与性能优化相关的问题。由于我的速度慢,而且是新手,所以我的代码似乎编写不正确,即使输出是正确的,但性能也很差 问题:我有0和1的位模式。我必须找到1的步幅(为我的分析计算contiguos 1)。我的数据帧是200000列x200行。现在速度非常慢,正在寻找一种更好的方法来完成完整的解决方案,或者用向量操作替换所有列的“for-loop”。例如: Input: 1,1,1,1,0,0,1,1,0,0,1,1,1 Output: 4,4,4,4,
Input: 1,1,1,1,0,0,1,1,0,0,1,1,1
Output: 4,4,4,4,0,0,2,2,0,0,3,3,3 (1 is replaced with the stride for 1)
我已经提取了一个示例代码以供审查。如果有人能帮上忙,我将不胜感激
start_time = timeit.default_timer()
# Small sample
AA = [1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0]
AB = [0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0]
AC = [1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0]
AD = [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
AE = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
df = pd.DataFrame({"A0": AA, "A1": AB, "A2": AB, "A3": AB, "A4": AB, "A5": AC, "A6": AD, "A7": AE, "A8": AE, "A9": AE})
# End of Debug Data Frame
df2=pd.DataFrame() # initialize to empty
print("Starting")
start_time = timeit.default_timer()
df1=pd.DataFrame(df != df.shift()).cumsum() # Operation-1: detects edges and increments at edge
print("Processing columns. Time=", timeit.default_timer() - start_time)
for c in df1.columns:
df2[c] = df1.groupby(c)[c].transform('count') * df[c] # This takes maximum time as I am counting column by column
print("Done Processing columns. Time=", timeit.default_timer() - start_time)
对于我的数据帧(200000列x200行),“For循环”需要700秒
Starting
Processing columns. Time= 0.9377922620624304
Done Processing columns. Time= 701.7339988127351
Done generating data. Time= 702.0729111488909
这里有一个替代方案,在示例数据帧上,不确定速度上的差异是否显著,但应该在更大的数据帧上。其思想是沿行使用(一次针对每一列),将原始df用作布尔值,以
pd.NA
替换累计df中的值,其中df为1。然后,您需要玩一些bfill
,ffill
,以获得预期的结果
df_ = df.cumsum().mask(df.astype(bool)) # Removing pd.NaT helped
df2 = (df_.bfill() - df_.ffill().fillna(0)).fillna(0)
print(df2)
A0 A1 A2 A3 A4 A5 A6 A7 A8 A9
0 1 0 0 0 0 2 0 10 10 10
1 0 8 8 8 8 2 1 10 10 10
2 0 8 8 8 8 0 0 10 10 10
3 2 8 8 8 8 2 1 10 10 10
4 2 8 8 8 8 2 0 10 10 10
5 0 8 8 8 8 0 1 10 10 10
6 0 8 8 8 8 0 0 10 10 10
7 0 8 8 8 8 0 1 10 10 10
8 1 8 8 8 8 1 0 10 10 10
9 0 0 0 0 0 0 1 10 10 10
10 1 1 1 1 1 1 0 0 0 0
11 0 0 0 0 0 0 1 0 0 0
12 5 5 5 5 5 5 0 0 0 0
13 5 5 5 5 5 5 1 0 0 0
14 5 5 5 5 5 5 0 0 0 0
15 5 5 5 5 5 5 1 0 0 0
16 5 5 5 5 5 5 0 0 0 0
17 0 0 0 0 0 0 1 0 0 0
18 0 0 0 0 0 0 0 0 0 0
19 0 0 0 0 0 0 0 0 0 0
非常感谢您的回复。它在较小的测试序列上测试得很好。当我移动到我的大型数据集时,即使超过一个小时,它也不会结束。我破坏了您在调试步骤中提供的解决方案,而“df_ufill().fillna(0)”将永远花费时间。有什么建议或替代方案吗?@Dsrivast我有点惊讶这部分这么长!据我所知,我唯一不经常使用的是前一行中的
pd.NA
。因此,试着只做df_979;=df.cumsum().mask(df.astype(bool))
看看您是否仍然存在效率问题。然后您可能需要强制转换为最终整数result@Ben-这就成功了,我看到性能提高了12倍。非常感谢你的帮助。有人把我的问题降级了。我花了很多时间做研究和遵循指导方针。请帮助我了解如何改进我的问题。随着我的学习,我想继续提问,而不必承受太大的降级压力。@Dsrivast很高兴知道wihtout pd.NA效果更好,我将与pd.NA一起深入探讨这个性能问题。