【问题标题】:Pandas - Dataframe - Conditional add熊猫 - 数据框 - 条件添加
【发布时间】:2019-12-21 01:23:27
【问题描述】:

我想在我的数据框中添加一个新列。我有一个事件列表,如果其中任何一个与 0 不同,则新列中的行的值应为 1。

我认为它应该很简单,但我对python相当陌生。

数据框如下所示:

df = pd.DataFrame({"ID":[1,1,2,3],"Date":["01/01/2019","01/01/2019","02/01/2019","02/01/2019"],"Event_1":[1,0,0,0],"Event_2":[1,0,0,1],"Event_3":[0,1,0,1],"Other":[0,0,0,1]})

print(df)
ID    Date         Event_1 Event_2 Event_3 Other
1     01/01/2019   1       1       0       0
1     01/01/2019   0       0       1       0
2     02/01/2019   0       0       0       0
3     02/01/2019   0       1       1       1

应该是这样的:

ID    Date         Event_1 Event_2 Event_3 Other Conditional_row
1     01/01/2019   1       1       0       0     1
1     01/01/2019   0       0       1       0     1
2     02/01/2019   0       0       0       0     0
3     02/01/2019   0       1       1       1     1

最简单的方法是什么?什么是最好的?

【问题讨论】:

    标签: python pandas conditional-statements


    【解决方案1】:

    假设您的数据框存储在名为df 的对象中。我相信这是最有效的方法:

    df["Conditional_row"] = 0
    df.loc[df[["Event_1","Event_2","Event_3","Other"]].sum(axis=1) > 0, "Conditional_row"] = 1
    

    输出如下所示:

    print(df)
       ID        Date  Event_1  Event_2  Event_3  Other  Conditional_row
    0   1  01/01/2019        1        1        0      0                1
    1   1  01/01/2019        0        0        1      0                1
    2   2  02/01/2019        0        0        0      0                0
    3   3  02/01/2019        0        1        1      1                1
    

    我在这里所做的是:

    1. 我创建了一个用零填充的新列。
    2. 我选择了列表["Event_1","Event_2","Event_3","Other"] 中列的逐行总和大于1 的所有行。
    3. 满足该条件的行的列"Conditional_row" 将更新为值 1。

    代码df[["Event_1","Event_2","Event_3","Other"]].sum(axis=1) > 0 称为mask,它返回一个布尔数组(一个用TrueFalse 值填充的向量)。它选择返回值为True 的所有行。通常,使用布尔数组进行切片是操作数据帧的最有效方式。

    【讨论】:

      【解决方案2】:

      或使用:

      df['Conditional_row'] = df[['Event_1', 'Event_2', 'Event_3', 'Other']].ne(0).any(1).astype(int)
      

      现在:

      print(df)
      

      输出:

         ID        Date  Event_1  Event_2  Event_3  Conditional_row
      0   1  01/01/2019        1        1        0                1
      1   1  01/01/2019        0        0        1                1
      2   2  02/01/2019        0        0        0                0
      3   3  02/01/2019        0        1        1                1
      

      【讨论】:

      • 它看起来很容易实现,但对我来说会引发 TypeError:Cannot convert bool to numpy.ndarray 我的行列表在:event_list = ("event_1","event_2","event_2","event_3","other") 我试图替换 ['Event_1', ' Event_2', 'Event_3'] 为event_list
      • @JesperMølgaard 添加了其他
      【解决方案3】:

      使用DataFrame.filtereqany

      首先我们filterEventOther 开头的列。然后我们检查行中的any 是否为eq(等于)1

      df['Conditional_row'] = df.filter(regex="^Event|^Other").eq(1).any(axis=1).astype(int)
      
         ID        Date  Event_1  Event_2  Event_3  Other  Conditional_row
      0   1  01/01/2019        1        1        0      0                1
      1   1  01/01/2019        0        0        1      0                1
      2   2  02/01/2019        0        0        0      0                0
      3   3  02/01/2019        0        1        1      1                1
      

      【讨论】:

      • 我有一个行列表:event_list = ("event_1","event_2","event_2","event_3","other") 当我用like='Event 替换event list 时,我得到:ValueError: cannot reindex from a duplicate axis
      • 查看我的编辑,其中还包括检查Other 列。 @JesperMølgaard
      【解决方案4】:

      使用filter + any

      由于所有非零整数在 Python 中都是 Truthy,因此直接在 DataFrame 上调用 any 会产生正确的掩码。由于您想要整数输出,我们可以使用内存高效的view 将布尔掩码视为整数类型。


      df.filter(like="Event").any(1).view('i1')
      

      0    1
      1    1
      2    0
      3    1
      dtype: int8
      

      【讨论】:

      • 几乎可以正常工作了。它现在不会引发错误。但由于某种原因,它将所有值设置为 0
      猜你喜欢
      • 1970-01-01
      • 2021-12-16
      • 2017-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-21
      • 2016-12-11
      • 2017-08-21
      相关资源
      最近更新 更多