根据多个其他列中部分字符串的存在来创建列

时间:2019-01-07 17:43:15

标签: python string pandas

我有一个名为df的数据框,看起来与此类似(除了'mat_deliv'列的数量上升到mat_deliv_8,并且有几百个客户端-我在这里进行了简化)。

Client_ID  mat_deliv_1  mat_deliv_2  mat_deliv_3  mat_deliv_4
C1019876   xxx,yyy,zzz  aaa,bbb,xxx  ccc          ddd
C1018765   yyy,zzz      xxx          bbb          None
C1017654   yyy,xxx      aaa,bbb      ccc          ddd
C1016543   aaa,bbb      ccc          None         None
C1019876   yyy          None         None         None

我想创建一个名为xxx_deliv的新列,其中包含两个值01。如果xxx_deliv1mat_deliv_1mat_deliv_2中的任何一个包含mat_deliv_3,我想将mat_deliv_4设置为等于xxx,和0(如果没有)。

因此,我想添加一个示例为df的列,如下所示:

Client_ID  mat_deliv_1  mat_deliv_2  mat_deliv_3  mat_deliv_4  xxx_deliv
C1019876   xxx,yyy,zzz  aaa,bbb,xxx  ccc          ddd          1
C1018765   yyy,zzz      xxx          bbb          None         1
C1017654   yyy,xxx      aaa,bbb      ccc          ddd          1
C1016543   aaa,bbb      ccc          None         None         0
C1019876   yyy          None         None         None         0

我知道以下代码可以完成所需的任务:

df['xxx_deliv'] = 0
df.loc[(df.Mat_deliv_1.str.contains("xxx", na=False)) |
       (df.Mat_deliv_2.str.contains("xxx", na=False)) |
       (df.Mat_deliv_3.str.contains("xxx", na=False)) |
       (df.Mat_deliv_4.str.contains("xxx", na=False)),
       'xxx_deliv'] = 1

但是我希望能够做到这一点,而不必遍历每个单独的列-我需要能够一次搜索多个列。

2 个答案:

答案 0 :(得分:3)

您需要单独检查每一列。您可以通过apply来执行此操作,检查字符串是否包含目标文本。然后将any应用于行(通过指定axis=1)。通过.astype(int)将布尔结果转换为整数,然后使用assign将其作为新列添加到数据框。

我使用loc[:, target_cols]将搜索范围指定为数据框中的所有行以及所有选定的target_cols

target_cols = ['mat_deliv_1', 'mat_deliv_2', 'mat_deliv_3', 'mat_deliv_4']
df = (df
      .assign(xxx_deliv=df.loc[:, target_cols].apply(lambda col: col.str.contains('xxx'))
      .any(axis=1)
      .astype(int))
>>> df
  Client_ID  mat_deliv_1  mat_deliv_2 mat_deliv_3 mat_deliv_4  xxx_deliv
0  C1019876  xxx,yyy,zzz  aaa,bbb,xxx         ccc         ddd          1
1  C1018765      yyy,zzz          xxx         bbb        None          1
2  C1017654      yyy,xxx      aaa,bbb         ccc         ddd          1
3  C1016543      aaa,bbb          ccc        None        None          0
4  C1019876          yyy         None        None        None          0

答案 1 :(得分:2)

您可以使用apply

def contains(xs, pat='xxx'):
    return int(any(pat in x for x in xs.values))


df['xxx_deliv'] = df[['mat_deliv_1', 'mat_deliv_2', 'mat_deliv_3', 'mat_deliv_4']].apply(contains, axis=1)
print(df)

输出

  Client_ID  mat_deliv_1    ...    mat_deliv_4 xxx_deliv
0  C1019876  xxx,yyy,zzz    ...            ddd         1
1  C1018765      yyy,zzz    ...           None         1
2  C1017654      yyy,xxx    ...            ddd         1
3  C1016543      aaa,bbb    ...           None         0
4  C1019876          yyy    ...           None         0

[5 rows x 6 columns]