【问题标题】:Calculate the average of sections of a column with condition met to create new dataframe计算满足条件的列部分的平均值以创建新数据框
【发布时间】:2021-09-13 05:19:12
【问题描述】:

我有下面的数据表

A = [2, 3, 1, 2, 4, 1, 5, 3, 1, 7, 5]
B = [0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0]
df = pd.DataFrame({'A':A, 'B':B})

当连续行看到 B 列等于 1 时,我想计算 A 列的平均值。B 列等于 0 的所有行都被忽略,随后创建一个新的数据框,如下所示:

感谢您的帮助!

【问题讨论】:

    标签: python pandas dataframe conditional-statements slice


    【解决方案1】:

    关键字:groupbyshiftmean


    代码:

    df_result=df.groupby((df['B'].shift(1,fill_value=0)!= df['B']).cumsum()).mean()
    df_result=df_result[df_result['B']!=0]
    
    df_result
         A    B
    1  2.0  1.0
    3  3.0  1.0
    

    您可能已经注意到,您首先需要确定具有相同值的连续行块。 一种方法是将 B 移动一行,然后将其与自身进行比较。

    df['B_shifted']=df['B'].shift(1,fill_value=0) # fill_value=0 to return int and replace Nan with 0's
    
    df['A']                     =[2, 3, 1, 2, 4, 1, 5, 3, 1, 7, 5]
    df['B']                     =[0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0]
    df['B_shifted']             =[0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0]
    (df['B_shifted'] != df['B'])=[F, T, F, F, T, F, T, F, F, T, F]
                                    [↑      ][↑   ][↑      ][↑   ] 
    

    现在我们可以使用 groupby pandas 方法如下:

    df_grouped=df.groupby((df['B_shifted'] != df['B']).cumsum())
    

    现在,如果我们循环进入 DtaFrameGroupBy 对象 df_grouped 我们将看到以下元组:

    (0,    A  B  B_shifted
    0  2  0          0)
    (1,    A  B  B_shifted
    1  3  1          0
    2  1  1          1
    3  2  1          1)
    (2,    A  B  B_shifted
    4  4  0          1
    5  1  0          0)
    (3,    A  B  B_shifted
    6  5  1          0
    7  3  1          1
    8  1  1          1)
    (4,     A  B  B_shifted
    9   7  0          1
    10  5  0          0)
     
    

    我们现在可以简单地计算平均值并过滤零值,如下所示

    df_result=df_grouped.mean()
    df_result=df_result[df_result['B']!=0][['A','B']]
    

    参考资料:(link, link)。

    【讨论】:

      【解决方案2】:
      df1 = df.groupby((df['B'].shift() != df['B']).cumsum()).mean().reset_index(drop=True)
      df1 = df1[df1['B'] == 1].astype(int).reset_index(drop=True)
      df1
      

      输出

          A   B
      0   2   1
      1   3   1
      

      说明

      我们正在使用 pd.shift 检查 B 的每一行的值是否不等于下一个值,如果是,那么我们将对这些值进行分组并计算其平均值并将其分配给新的数据帧 df1

      因为我们有所有连续 0 和 1 的组的平均值,所以我们只过滤 B==1 的值。

      【讨论】:

      • 这种方法有效,但是如果我将 mean 更改为 std,它会将 B 列中的所有值转换为 0,我不再可以进行任何过滤。还有其他想法吗?
      • 我最终创建了一个数据框,其中包含 A 列的所有统计信息,并从 groupby.mean 插入 B 列以完成这项工作。
      【解决方案3】:

      试试:

      m = (df.B != df.B.shift(1)).cumsum() * df.B
      df_out = df.groupby(m[m > 0])["A"].mean().reset_index(drop=True).to_frame()
      df_out["B"] = 1
      print(df_out)
      

      打印:

         A  B
      0  2  1
      1  3  1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-13
        • 2019-06-16
        • 1970-01-01
        • 2021-12-23
        相关资源
        最近更新 更多