【问题标题】:Reversed cumulative sum of a column in pandas.DataFramepandas.DataFrame 中列的反向累积总和
【发布时间】:2016-10-18 18:14:49
【问题描述】:

我有一个pandas DataFrame,其中一个布尔列按另一列排序,需要计算布尔列的反向累积和,即从当前行到底部的真值数量。

例子

In [13]: df = pd.DataFrame({'A': [True] * 3 + [False] * 5, 'B': np.random.rand(8) })

In [15]: df = df.sort_values('B')

In [16]: df
Out[16]:
       A         B
6  False  0.037710
2   True  0.315414
4  False  0.332480
7  False  0.445505
3  False  0.580156
1   True  0.741551
5  False  0.796944
0   True  0.817563

我需要一些可以给我一个新列的值

3
3
2
2
2
2
1
1

也就是说,对于每一行,它应该在该行和下面的行中包含一定数量的 True 值。

我使用.iloc[::-1] 尝试了各种方法,但结果并不理想。

我似乎遗漏了一些明显的信息。我昨天才开始使用 Pandas。

【问题讨论】:

    标签: python pandas dataframe reverse


    【解决方案1】:

    反转A列,取cumsum,然后再次反转:

    df['C'] = df.loc[::-1, 'A'].cumsum()[::-1]
    

    import pandas as pd
    df = pd.DataFrame(
        {'A': [False, True, False, False, False, True, False, True],
         'B': [0.03771, 0.315414, 0.33248, 0.445505, 0.580156, 0.741551, 0.796944, 0.817563],},
         index=[6, 2, 4, 7, 3, 1, 5, 0])
    df['C'] = df.loc[::-1, 'A'].cumsum()[::-1]
    print(df)
    

    产量

           A         B  C
    6  False  0.037710  3
    2   True  0.315414  3
    4  False  0.332480  2
    7  False  0.445505  2
    3  False  0.580156  2
    1   True  0.741551  2
    5  False  0.796944  1
    0   True  0.817563  1
    

    或者,您可以计算A 列中Trues 的数量并减去(移位的)cumsum:

    In [113]: df['A'].sum()-df['A'].shift(1).fillna(0).cumsum()
    Out[113]: 
    6    3
    2    3
    4    2
    7    2
    3    2
    1    2
    5    1
    0    1
    Name: A, dtype: object
    

    但这要慢得多。使用IPython 执行基准测试:

    In [116]: df = pd.DataFrame({'A':np.random.randint(2, size=10**5).astype(bool)})
    
    In [117]: %timeit df['A'].sum()-df['A'].shift(1).fillna(0).cumsum()
    10 loops, best of 3: 19.8 ms per loop
    
    In [118]: %timeit df.loc[::-1, 'A'].cumsum()[::-1]
    1000 loops, best of 3: 701 µs per loop
    

    【讨论】:

      【解决方案2】:

      这可行,但速度很慢......就像@unutbu 回答一样。 True 解析为 1。在 False 或任何其他值上失败。

      df[2] = df.groupby('A').cumcount(ascending=False)+1
      df[1] = np.where(df['A']==True,df[2],None)
      df[1] = df[1].fillna(method='bfill').fillna(0)
      del df[2]
      
            A         B    1
      # 3  False  0.277557  3.0
      # 7  False  0.400751  3.0
      # 6  False  0.431587  3.0
      # 5  False  0.481006  3.0
      # 1   True  0.534364  3.0
      # 2   True  0.556378  2.0
      # 0   True  0.863192  1.0
      # 4  False  0.916247  0.0
      

      【讨论】:

        【解决方案3】:

        类似于 unutbus 的第一个建议,但没有弃用的 ix:

        df['C']=df.A[::-1].cumsum()
        

        【讨论】:

        • 请注意,这可能会颠倒您对列 'C' 的期望顺序。详情见unutbu's answer
        【解决方案4】:

        如果想逐列反转累积和:

        (-df).cumsum(axis=1).add(1).shift(1,axis=1,fill_value=1.0)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-01-15
          • 2018-07-02
          • 1970-01-01
          • 2018-02-28
          • 2019-02-15
          • 1970-01-01
          • 2020-03-12
          • 1970-01-01
          相关资源
          最近更新 更多