如何合并具有一定数量子字符串的字符串以在 Python 中的数据框中生成一些组

How to merge strings that have certain number of substrings in common to produce some groups in a data frame in Python

我问了这样一个问题。但这是一个简单的。这已经解决了。 .

但是在这里,我有一个类似问题的高级版本:

我有一个示例数据:

a=pd.DataFrame({'ACTIVITY':['b,c','a','a,c,d,e','f,g,h,i','j,k,l','k,l,m']})

我想做的是合并一些字符串,如果它们有共同的子字符串。因此,在此示例中,字符串 'b,c'、'a'、'a,c,d,e' 应该合并在一起,因为它们可以相互链接。 'j,k,l' 和 'k,l,m' 应该在一组。最后,我希望我能有这样的东西:

               group
'b,c',         0
'a',           0
'a,c,d,e',     0
'f,g,h,i',     1
'j,k,l',       2
'k,l,m'        2

所以,我可以有三个组,并且任何两个组之间没有公共子字符串。

现在,我正在尝试建立一个相似性数据框,其中 1 表示两个字符串具有共同的子字符串。这是我的代码:

commonWords=1

for i in np.arange(a.shape[0]):
    a.loc[:,a.loc[i,'ACTIVITY']]=0

for i in a.loc[:,'ACTIVITY']:
    il=i.split(',')
    for j in a.loc[:,'ACTIVITY']:
        jl=j.split(',')
        c=[x in il for x in jl]
        c1=[x for x in c if x==True]
        a.loc[(a.loc[:,'ACTIVITY']==i),j]=1 if len(c1)>=commonWords else 0
    
a

结果是:

    ACTIVITY    b,c     a   a,c,d,e     f,g,h,i     j,k,l   k,l,m
0   b,c          1      0       1           0       0       0
1   a            0      1       1           0       0       0
2   a,c,d,e      1      1       1           0       0       0
3   f,g,h,i      0      0       0           1       0       0
4   j,k,l        0      0       0           0       1       1
5   k,l,m        0      0       0           0       1       1

在这段代码中,commonWords 表示我希望两个字符串共有多少个子字符串。例如,如果 commonWords=2,那么只有当两个字符串中有两个或两个以上的子字符串时,才会将它们合并在一起。当 commonWords=2 时,组应该是:

               group
'b,c',         0
'a',           1
'a,c,d,e',     2
'f,g,h,i',     3
'j,k,l',       4
'k,l,m'        4

使用:

a=pd.DataFrame({'ACTIVITY':['b,c','a','a,c,d,e','f,g,h,i','j,k,l','k,l,m']})


from itertools import combinations, chain
from collections import Counter

#split values by , to lists
splitted = a['ACTIVITY'].str.split(',')

commonWords=2
#create edges (can only connect two nodes)
L2_nested = [list(combinations(l,commonWords)) for l in splitted]
L2 = list(chain.from_iterable(L2_nested))

#convert values to sets
f1 = [set(k) for k, v in Counter(L2).items() if v >= commonWords]
f2 = [set(x) for x in splitted]

#create new columns for matched sets
for val in f1:
    j = ','.join(val)
    a[j] = [j if len(val & x) == commonWords else np.nan for x in f2]
print (a)

#forward filling values of new columns and use factorize for groups
new = pd.factorize(a[['ACTIVITY']].assign(ACTIVITY = a.index).ffill(axis=1).iloc[:, -1])[0]

a = a[['ACTIVITY']].assign(group = new)
print (a)
  ACTIVITY  group
0      b,c      0
1        a      1
2  a,c,d,e      2
3  f,g,h,i      3
4    j,k,l      4
5    k,l,m      4