我正在学习Pandas数据帧和一个与性能优化有关的问题。由于我是一个新手,所以我的代码似乎写得不正确,即使输出是正确的,性能也很差。
问题:我有0和1的位模式。我必须找到1的步幅(为我的分析计算1个连续数(。我的数据框架是200000列x 200行。它现在非常慢,正在寻找一种更好的方法来完成完整的解决方案,或者用矢量运算替换所有列的"for循环"。示例:
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列x 200行(,"For loop"需要700秒的
Starting
Processing columns. Time= 0.9377922620624304
Done Processing columns. Time= 701.7339988127351
Done generating data. Time= 702.0729111488909
这里有一个替代方案,在样本数据帧上,不确定速度的差异是否显著,但应该是更大的差异。其想法是沿着行使用cumsum
(一次针对每列(,使用具有原始df的mask
作为布尔值,用pd.NA
替换累积df中的值,其中df为1。然后你需要玩一些bfill
、ffill
和fillna
才能得到预期的结果。
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