计算一个字符串在多个字符串列中的出现次数[英] Count occurrences of a string in multiple string columns

本文是小编为大家收集整理的关于计算一个字符串在多个字符串列中的出现次数的处理方法,想解了计算一个字符串在多个字符串列中的出现次数的问题怎么解决?计算一个字符串在多个字符串列中的出现次数问题的解决办法?那么可以参考本文帮助大家快速定位并解决问题。

问题描述

i有一个称为df的数据框,看起来与此相似(除了'mat_deliv'列的数量达到mat_deliv_8,还有数百个客户端和Client_ID和mat_deliv_1之间的许多其他列.我在这里简化了它).

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

我想创建一个名为xxx_count的新列,该列数计数xxx出现在mat_deliv_1,mat_deliv_2,mat_deliv_2,mat_deliv_3和mat_deliv_4中的次数.值应该像这样:

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

我尝试了以下代码:

df = df.assign(xxx_count=df.loc[:, "mat_deliv_1":"mat_deliv_4"].\
               apply(lambda col: col.str.count('xxx')).fillna(0).astype(int))

但不会产生计数,仅是二进制变量,其中0 =无xxx和1 = =在四个mat_deliv列中的至少一个中存在xxx的情况.

nb:这是此处问的一个后续问题:https://stackoverflow.com/questions/54079267/creating-a-col-a-column--collumn-lation-presence-n-presence-of--presence-of-基于多个其他列中字符串的一部分创建列

推荐答案

在计数之前尝试水平加入它们?

df['counts'] = (df.loc[:, "mat_deliv_1":"mat_deliv_4"]
                  .fillna('')
                  .agg(','.join, 1)
                  .str.count('xxx'))
df
  Client_ID  mat_deliv_1  mat_deliv_2 mat_deliv_3 mat_deliv_4  counts
0  C1019876  xxx,yyy,zzz  aaa,bbb,xxx         xxx         ddd       3
1  C1018765      yyy,zzz          xxx         xxx         NaN       2
2  C1017654      yyy,xxx      aaa,bbb         ccc         ddd       1
3  C1016543      aaa,bbb          ccc         NaN         NaN       0
4  C1019876          yyy          NaN         NaN         NaN       0

假设" XXX"仅出现到每列仅一次.如果发生不止一次,它将计算每次发生.


另一个选项涉及stack:

df['counts'] = (
    df.loc[:, "mat_deliv_1":"mat_deliv_4"].stack().str.count('xxx').sum(level=0))
df
  Client_ID  mat_deliv_1  mat_deliv_2 mat_deliv_3 mat_deliv_4  counts
0  C1019876  xxx,yyy,zzz  aaa,bbb,xxx         xxx         ddd       3
1  C1018765      yyy,zzz          xxx         xxx         NaN       2
2  C1017654      yyy,xxx      aaa,bbb         ccc         ddd       1
3  C1016543      aaa,bbb          ccc         NaN         NaN       0
4  C1019876          yyy          NaN         NaN         NaN       0

使用str.contains:

,可以轻松地修改此仅计算首次出现.

df['counts'] = (
    df.loc[:, "mat_deliv_1":"mat_deliv_4"].stack().str.contains('xxx').sum(level=0))

如果" xxx"可能成为子字符串,请首先拆分,然后计算:

df['counts'] = (df.loc[:, "mat_deliv_1":"mat_deliv_4"]
                  .stack()
                  .str.split(',', expand=True)
                  .eq('xxx')
                  .any(1)  # change to `.sum(1)` to count all occurrences
                  .sum(level=0))

供性能,使用列表理解:

df['counts'] = [
    ','.join(x).count('xxx') 
    for x in df.loc[:, "mat_deliv_1":"mat_deliv_4"].fillna('').values
]
df
  Client_ID  mat_deliv_1  mat_deliv_2 mat_deliv_3 mat_deliv_4  counts
0  C1019876  xxx,yyy,zzz  aaa,bbb,xxx         xxx         ddd       3
1  C1018765      yyy,zzz          xxx         xxx         NaN       2
2  C1017654      yyy,xxx      aaa,bbb         ccc         ddd       1
3  C1016543      aaa,bbb          ccc         NaN         NaN       0
4  C1019876          yyy          NaN         NaN         NaN       0

为什么比使用str方法或apply更快?请参阅 for Pandas with-should-i-care">与Pandas一起循环 - 我什么时候应该关心?.

其他推荐答案

使用str.findall

df.iloc[:,1:].apply(lambda x : x.str.findall('xxx')).sum(1).str.len()
Out[433]: 
0    3
1    2
2    1
3    0
4    0
dtype: int64

其他推荐答案

您可以使用,拆分,然后在lambda中使用lambda.该解决方案的优点是,如果存在xxx作为yyy的子字符串,则不会看到不正确的结果.

df['xxx_count'] = df.filter(like='mat_deliv').apply(lambda x: x.str.split(',')\
                                                    .apply(lambda x: 'xxx' in x)).sum(1)

print(df)

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

或更好地使用功能:

def sum_counts(series, value):
    def finder(item, value):
        return value in item
    return series.str.split(',').apply(finder, value=value)

df['xxx_count'] = df.filter(like='mat_deliv').apply(sum_counts, value='xxx').sum(1)

本文地址:https://www.itbaoku.cn/post/1728126.html