【问题标题】:python pandas trying to reduce reliance on loopspython pandas 试图减少对循环的依赖
【发布时间】:2019-04-19 23:19:04
【问题描述】:

这是一个关于矢量化的一般问题,但我将使用一个示例来帮助提出这个问题。我有一个数据框dfdf[col_1] bool(真/假)。 在df[col_2] 中,我想根据第1 列的前五行df[col_1][i-6:i-1] 是否包含df[col_1][i] 的匹配项来返回另一个真/假。

这是我现在正在使用的循环,但它是众多循环之一,所以我认为随着数据变大,它们一定会减慢速度:

for i in df.index:
  if i < 6:
    df[col_2][i] = 0.
  else:
    df[col_2][i] = df[col_1][i] not in tuple(df[col_1].ix[i-6:i-1,col_1)

...输出如下所示:

.   col_1   col_2
0   TRUE    
1   TRUE    
2   TRUE    
3   TRUE    
4   FALSE   
5   FALSE   FALSE
6   FALSE   FALSE
7   FALSE   FALSE
8   FALSE   FALSE
9   TRUE    TRUE
10  FALSE   FALSE
11  FALSE   FALSE
12  FALSE   FALSE
13  FALSE   FALSE
14  TRUE    FALSE
15  TRUE    FALSE
16  TRUE    FALSE
17  TRUE    FALSE
18  TRUE    FALSE
19  TRUE    FALSE
20  FALSE   TRUE

如何在带有矢量化的 pandas 中做到这一点 - 也许使用 shift() 或偏移函数?

【问题讨论】:

  • 将样本数据和结果放入问题中总是一个好主意......我无法想到一个简洁的方法来做到这一点,但它肯定会更快使用shift() 执行上述操作,即使您有 5 个。此外,上面的代码不是工作代码,因此很难检查可能的答案(没有工作代码和/或示例结果)。
  • 明白,我已经添加了结果应该是什么。不知道为什么它不起作用 - 我更改了名称以使其更易于阅读,但应该仍然有效。
  • 谢谢,只要显示结果就足够了。只需要明确你想要做什么。

标签: python pandas vectorization


【解决方案1】:

这是一个简单的矢量化解决方案,应该非常快,尽管可能有一种更优雅的方式来编写它。如果您愿意,可以忽略前 5 行或将它们覆盖为 NaN。

df = pd.DataFrame({ 'col_1':[True,True,True,True,False,False,False,False,
                             False,True,False,False,False,False,True,True,
                             True,True,True,True,False] })

df['col_2'] = ((df!=df.shift(1)) & (df!=df.shift(2)) & (df!=df.shift(3)) & 
               (df!=df.shift(4)) & (df!=df.shift(5)))

如果速度真的很重要,您可以执行以下操作。它比上面的速度快 3 倍以上,并且可能与您在这里可以做的一样高效。这只是利用 rolling_sum() 将布尔值解释为 0/1 的事实,您只需要知道总和是 0 还是 5。

df['rollsum'] = pd.rolling_sum(df.col_1,6) - df.col_1
df['col_3'] = ( ((df.col_1==True ) & (df.rollsum==0)) 
              | ((df.col_1==False) & (df.rollsum==5)) )

    col_1  col_2  rollsum  col_3
0    True   True      NaN  False
1    True  False      NaN  False
2    True  False      NaN  False
3    True  False      NaN  False
4   False   True      NaN  False
5   False  False        4  False
6   False  False        3  False
7   False  False        2  False
8   False  False        1  False
9    True   True        0   True
10  False  False        1  False
11  False  False        1  False
12  False  False        1  False
13  False  False        1  False
14   True  False        1  False
15   True  False        1  False
16   True  False        2  False
17   True  False        3  False
18   True  False        4  False
19   True  False        5  False
20  False   True        5   True

【讨论】:

  • 太好了,谢谢。假设将 df['col_1'] 替换为 df 将以相同的方式工作。非常感谢你看一看。
  • 是的,应该可以的。我只是选择了快捷方式,因为 'col_1' 是我的示例中唯一的变量。
  • 两者都有效,但第二个版本会动态调整以适应不同的回溯期。此外,只需更换单个循环即可将我的总运行时间减少 10-15%。非常聪明,再次感谢。
猜你喜欢
  • 1970-01-01
  • 2012-07-16
  • 2011-09-18
  • 2017-07-13
  • 1970-01-01
  • 2010-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多