Python:确定存储在数据框中的三个文本字符串是不是有任何共同的单词

Posted

技术标签:

【中文标题】Python:确定存储在数据框中的三个文本字符串是不是有任何共同的单词【英文标题】:Python: determine if three text strings stored in a dataframe have any words in commonPython:确定存储在数据框中的三个文本字符串是否有任何共同的单词 【发布时间】:2018-10-19 14:35:31 【问题描述】:

假设我有以下数据框df

      A             B               C
0     mom;dad;son;  sister;son;     yes;no;maybe;
1     dad;          daughter;niece; no;snow;
2     son;dad;      cat;son;dad;    tree;dad;son;
3     daughter;mom; niece;          referee;
4     dad;daughter; cat;            dad;

并且您想检查在列ABC 之间是否存在共同词,如果存在则使用1 创建列D,如果存在则0没有。一个词要常见,它只出现在三列中的两列中就足够了。

结果应该是:

      A             B               C              D
0     mom;dad;son;  sister;son;     yes;no;maybe;  1
1     dad;          daughter;niece; no;snow;       0
2     son;dad;      cat;son;dad;    tree;dad;son;  1
3     daughter;mom; niece;          referee;       0
4     dad;daughter; cat;            dad;           1

我正在尝试通过这样做来实现这一点:

for index, row in df.iterrows():

    w1=row['A'].split(';')
    w2=row['B'].split(';')
    w3=row['C'].split(';')

    if len(set(w1).intersection(w2))>0 or len(set(w1).intersection(w3))>0 or len(set(w2).intersection(w3))>0:
        df['D'][index]==1
    else:
        df['D'][index]==0

但是,生成的 D 列仅包含 0,因为(可能)我没有将 w1 中的每个单词与 w2 和 w3 中的其他单词进行比较。我怎样才能做到这一点?

【问题讨论】:

【参考方案1】:

使用stack + pandas.Series.str.get_dummies

df.assign(
    D=df.stack().str.get_dummies(';').sum(level=0).gt(1).any(1).astype(int)
)

               A                B              C  D
0   mom;dad;son;      sister;son;  yes;no;maybe;  1
1           dad;  daughter;niece;       no;snow;  0
2       son;dad;     cat;son;dad;  tree;dad;son;  1
3  daughter;mom;           niece;       referee;  0
4  dad;daughter;             cat;           dad;  1

详情

请注意,当我们堆叠并获取虚拟对象时,中间结果如下所示:

     cat  dad  daughter  maybe  mom  niece  no  referee  sister  snow  son  tree  yes
0 A    0    1         0      0    1      0   0        0       0     0    1     0    0
  B    0    0         0      0    0      0   0        0       1     0    1     0    0
  C    0    0         0      1    0      0   1        0       0     0    0     0    1
1 A    0    1         0      0    0      0   0        0       0     0    0     0    0
  B    0    0         1      0    0      1   0        0       0     0    0     0    0
  C    0    0         0      0    0      0   1        0       0     1    0     0    0
2 A    0    1         0      0    0      0   0        0       0     0    1     0    0
  B    1    1         0      0    0      0   0        0       0     0    1     0    0
  C    0    1         0      0    0      0   0        0       0     0    1     1    0
3 A    0    0         1      0    1      0   0        0       0     0    0     0    0
  B    0    0         0      0    0      1   0        0       0     0    0     0    0
  C    0    0         0      0    0      0   0        1       0     0    0     0    0
4 A    0    1         1      0    0      0   0        0       0     0    0     0    0
  B    1    0         0      0    0      0   0        0       0     0    0     0    0
  C    0    1         0      0    0      0   0        0       0     0    0     0    0

先前的列嵌入在索引的第二级中。所以我想总结一下第一级,看看这个词出现了多少次。

总和中期看起来像:

   cat  dad  daughter  maybe  mom  niece  no  referee  sister  snow  son  tree  yes
0    0    1         0      1    1      0   1        0       1     0    2     0    1
1    0    1         1      0    0      1   1        0       0     1    0     0    0
2    1    3         0      0    0      0   0        0       0     0    3     1    0
3    0    0         1      0    1      1   0        1       0     0    0     0    0
4    1    2         1      0    0      0   0        0       0     0    0     0    0

请注意,我们在第 1 行捕获了 'son',在第 3 行捕获了 'dad''son',依此类推。

如果它出现在超过 1 列中(因此是 gt(1)),那么我想将它算作 1(因此是 any(1).astype(int))。

【讨论】:

这是一段非常简洁的代码,可能会受益于更多解释。 非常好的解决方案 :) +1 如果您的列具有诸如There are spaces in this header 之类的名称,D=df.stack() 部分如何工作?此外,您如何将其应用于现有数据框的选择,例如没有创建一个新的? @FaCoffee 你可以做几件事。一,您可以使用df['Name with spaces'] = ...df.stack().str.get_dummies(';').sum(level=0).gt(1).any(1).astype(int) 的结果直接放入数据框中,或者您可以通过解压缩字典df.assign(**'Name with spaces': df.stack().str.get_dummies(';').sum(level=0).gt(1).any(1).astype(int)) 继续利用assign 方法 啊,我想你的意思是你的示例数据框与列['A', 'B', 'C'] 实际上是['Col 1', 'Col 2', 'Col 3']?如果我是对的,那么是的,你的建议应该有效。 df[['Col 1', 'Col 2', 'Col 3']].stack()...【参考方案2】:

这个单线创建你需要的东西,使用collections.Counter:

from collections import Counter

df['D'] = df.applymap(lambda x: [i for i in x.split(';') if i]).apply(lambda x: int(Counter(x.A+x.B+x.C).most_common(1)[0][1]!=1), axis=1)

【讨论】:

【参考方案3】:

您可以通过修正错字来使用您的代码:将 == 替换为 =

【讨论】:

【参考方案4】:

试试这个:

def find_common(row):
     A_list=set(row['A'].rsplit(';')[:-1])
     B_list=set(row['B'].rsplit(';')[:-1])
     C_list=set(row['C'].rsplit(';')[:-1])
     if ((len(A_list.intersection(B_list))) or (len(B_list.intersection(C_list))) or (len(A_list.intersection(C_list)))):
        return 1
     else: 
        return 0  

df['D']=df.apply(find_common,axis=1)

【讨论】:

以上是关于Python:确定存储在数据框中的三个文本字符串是不是有任何共同的单词的主要内容,如果未能解决你的问题,请参考以下文章

在pandas数据框中搜索文本列而不进行循环

在文本框中显示数据库中的十进制值

使用 ASP.NET 通过 SQL 表显示存储在文本框中的数据

Android界面中一个文本框,返回时保存数据,

如何仅在多个自动完成文本框中的前 2 个字符之后才开始自动完成?

Python - 正则表达式将数据框中的一列拆分为 2 [重复]