【问题标题】:Speeding up pandas loop counter加快熊猫循环计数器
【发布时间】:2018-09-26 11:18:18
【问题描述】:

所以我目前正在熊猫 df 中逐行更新计数器,我认为这不是最快的处理方式。

下面是我正在使用的 df 的简化版本,我有两个计数器 C1 计数每个“S”类别日,C2 计数每次从“N”切换到“S”而不是从“B”到“S”,除非它是从“N”到“B”到“S”。

这是通过 for 循环和 if 语句完成的,但超过 170 万行时速度非常慢。 我进行了相当多的搜索,似乎找不到更“熊猫/numpy”的方法。

任何正确方向的想法或指示将不胜感激。

  Date  Category C1 C2
1/1/2015    N   0   0
1/2/2015    N   0   0
1/5/2015    S   1   1
1/5/2015    S   2   1
1/6/2015    S   3   1
1/6/2015    S   4   1
1/7/2015    N   4   1
1/7/2015    N   4   1
1/12/2015   N   4   1
1/12/2015   N   4   1
1/13/2015   N   4   1
1/13/2015   S   5   2
1/15/2015   S   6   2
1/15/2015   B   7   2
1/16/2015   S   8   2
1/16/2015   S   9   2
1/16/2015   N   8   2
1/21/2015   N   8   2
1/21/2015   S   9   3
1/22/2015   S   10  3

【问题讨论】:

    标签: python pandas loops for-loop


    【解决方案1】:

    一般情况下,您想使用.cumsum() 来累积值,而.shift() 当您想检查上一个或下一个值时。知道True 等价于数学表达式中的1 可以为我们节省一点时间。

    对于给出的示例值,以下将起作用:

    df['C1'] = (df['Category'] == 'S').cumsum()
    df['C2'] = ((df['Category'] == 'S') & (df['Category'].shift(1) == 'N')).cumsum()
    

    但是,有的部分

    不是从“B”到“S”,除非是从“N”到“B”到“S”。

    使后者更复杂一些。但是,应该可以使用稍微复杂的设置:

    df['C2'] = (((df['Category'] == 'S') & (df['Category'].shift(1) == 'N')) |
                ((df['Category'] == 'S') & (df['Category'].shift(1) == 'B') & (df['Category'].shift(2) == 'N'))).cumsum()
    

    这假定您要计算的唯一“B 到 S”行是第 n-1 行为 N、第 n 行为 B、第 n+1 行为 S 的行。不包括所有其他实例。

    【讨论】:

    • 谢谢,这正是我想要的。但是,使用 for 循环,如果类别的第一行是“S”,我可以将计数器的第一行设置为 1,使用矢量化方法有什么简单的方法吗?即没有从“N”过渡
    • @ar1847 这是'C2'列的吗?
    • 我会的。如果那天的类别是“S”,我希望 C2 的第一行是 1。我是通过 if df['Category'].iloc[0] == 'S': df['C2' ].iloc[0] = 1
    • if df['Category'].iloc[0] == 'S': df['C2'] += 1 怎么样?
    【解决方案2】:

    你可以只用一个循环来解决它。循环的主要焦点是计数 S,比如 counter1。在for循环内部,检查前一个是否为N,如果是,则添加到counter2。否则,如果前一个是B,前一个是N,则加到counter2。

    例如,如果您有一个类别列表,您可以:

    C1, C2 = 0, 0
    for i in range(len(category)):
        if category[i] == 'S':
            C1 += 1
            if category[max(0, i-1)] =='N':
                C2 += 1
            elif (category[max(0, i-1)]=='B') and (category[max(0, i-2)]=='N'):
                C2 += 1
    

    这样,您可以最大限度地减少 for 循环的数量。希望对您有所帮助。

    【讨论】:

    • 最小化 for 循环的数量并不会最小化它所花费的时间——pandas 的矢量化函数应该会更快
    猜你喜欢
    • 2018-05-14
    • 2018-08-10
    • 1970-01-01
    • 2021-10-26
    • 2020-02-22
    • 2018-12-11
    • 2021-06-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多