【问题标题】:Python Data Frame: cumulative sum of column until condition is reached and return the indexPython数据框:列的累积总和,直到达到条件并返回索引
【发布时间】:2017-05-20 05:04:15
【问题描述】:

我是 Python 新手,目前面临一个我无法解决的问题。我真的希望你能帮助我。英语不是我的母语,所以如果我不能正确表达自己,我很抱歉。

假设我有一个包含两列的简单数据框:

index  Num_Albums  Num_authors
0      10          4
1      1           5
2      4           4
3      7           1000
4      1           44
5      3           8

Num_Abums_tot = sum(Num_Albums) = 30

我需要对Num_Albums中的数据进行累计求和,直到达到某个条件。注册达到条件的索引,从Num_authors获取对应的值。

示例: Num_Albums 的累积总和,直到总和等于 30 的 50% ± 1/15 (--> 15±2):

10 = 15±2? No, then continue;
10+1 =15±2? No, then continue
10+1+41 = 15±2? Yes, stop. 

在索引 2 处达到条件。然后在该索引处获取 Num_AuthorsNum_Authors(2)=4

我想看看pandas 中是否已经实现了一个函数,然后才开始考虑如何使用 while/for 循环来实现......

[我想指定我想在相关索引处检索值的列(当我有 4 列并且我想对第 1 列中的元素求和时,这会派上用场,条件达到 =yes 然后得到第 2 列中的对应值;然后对第 3 列和第 4 列执行相同操作)]。

【问题讨论】:

    标签: python pandas dataframe sum


    【解决方案1】:

    选项 - 1:

    您可以使用cumsum 计算累积和。然后使用 np.isclose 和它的内置容差参数来检查该系列中存在的值是否在指定的阈值 15 +/- 2 内。这将返回一个布尔数组。

    通过np.flatnonzero,返回满足True 条件的索引的序数值。我们选择True 值的第一个实例。

    最后,使用.iloc 根据之前计算的索引检索您需要的列名的值。

    val = np.flatnonzero(np.isclose(df.Num_Albums.cumsum().values, 15, atol=2))[0]
    df['Num_authors'].iloc[val]      # for faster access, use .iat 
    4
    

    当在series上执行np.isclose后转换为数组:

    np.isclose(df.Num_Albums.cumsum().values, 15, atol=2)
    array([False, False,  True, False, False, False], dtype=bool)
    

    选项 - 2:

    cumsum 计算系列上使用pd.Index.get_loc,它还支持nearest 方法上的tolerance 参数。

    val = pd.Index(df.Num_Albums.cumsum()).get_loc(15, 'nearest', tolerance=2)
    df.get_value(val, 'Num_authors')
    4
    

    选项 - 3:

    使用idxmax 查找在subabscumsum 系列进行操作后创建的布尔掩码的True 值的第一个索引:

    df.get_value(df.Num_Albums.cumsum().sub(15).abs().le(2).idxmax(), 'Num_authors')
    4
    

    【讨论】:

      【解决方案2】:

      我觉得你可以直接加一列,累计和为:

      In [3]: df
      Out[3]: 
         index  Num_Albums  Num_authors
      0      0          10            4
      1      1           1            5
      2      2           4            4
      3      3           7         1000
      4      4           1           44
      5      5           3            8
      
      In [4]: df['cumsum'] = df['Num_Albums'].cumsum()
      
      In [5]: df
      Out[5]: 
         index  Num_Albums  Num_authors  cumsum
      0      0          10            4      10
      1      1           1            5      11
      2      2           4            4      15
      3      3           7         1000      22
      4      4           1           44      23
      5      5           3            8      26
      

      然后在cumsum 列上应用您想要的条件。例如,您可以使用where 根据过滤器获取整行。设置容差tol

      In [18]: tol = 2
      
      In [19]: cond = df.where((df['cumsum']>=15-tol)&(df['cumsum']<=15+tol)).dropna()
      
      In [20]: cond
      Out[20]: 
         index  Num_Albums  Num_authors  cumsum
      2    2.0         4.0          4.0    15.0
      

      【讨论】:

      • 这太棒了!现在,假设我想提取与存储在数组(名为 ARRAY)中的条件相对应的值,并将这些值传递给列表(名为:cond)或另一个数组。在 matlab 语法中,我会执行以下操作:for i in ARRAY: cond[i] = df.where((df['cumsum'] >=ARRAY[i]-tol)&(...)).dropna( ) 我如何在 python 中做到这一点?再开一个问题会更合适吗?
      • 是的,请保持一篇文章,一题的风格。
      • 我做到了,有时间想看看就在这里。我会很感激的。 stackoverflow.com/questions/41545936/…
      【解决方案3】:

      这甚至可以通过以下代码来完成:

      def your_function(df):
           sum=0
           index=-1
           for i in df['Num_Albums'].tolist():
             sum+=i
             index+=1
             if sum == ( " your_condition " ):
                    return (index,df.loc([df.Num_Albums==i,'Num_authors']))
      

      一旦达到“你的条件”,这实际上会返回一个索引元组和 Num_authors 的相应值。

      甚至可以由

      作为数组返回
      def your_function(df):
           sum=0
           index=-1
           for i in df['Num_Albums'].tolist():
             sum+=i
             index+=1
             if sum == ( " your_condition " ):
                    return df.loc([df.Num_Albums==i,'Num_authors']).index.values
      

      我无法弄清楚您提到的累积和何时停止求和的条件,所以我在代码中将其称为“your_condition”!!

      我也是新手,希望对你有帮助!!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-28
        • 2020-03-30
        • 1970-01-01
        • 2020-08-24
        • 2019-05-05
        相关资源
        最近更新 更多