通过遍历同一列的行比较并找到最接近的匹配字符串

0 投票
1 回答
62 浏览
提问于 2025-04-14 16:36

我刚开始学习Python,想要从同一列中遍历行并获取输出。

# Import pandas library
import pandas as pd
 
# initialize list of lists
data = [[1, 'AA,AC,BC,DE'], [2, 'AA,AD,BC,D'], [3, 'A,C,BC,E'],[4, 'AA,AC,BC,DEEE'],[5, 'KK']]
 
# Create the pandas DataFrame
df = pd.DataFrame(data, columns=['rowid', 'Col1'])

输出表格:

data_out = [[1, 'AA,AC,BC,DE',2,'2,4'], [2, 'AA,AD,BC,D',2,'1,4'], [3, 'A,C,BC,E',1,'1,2,4'],[4, 'AA,AC,BC,DEEE',2,'1,2'],[5, 'KK',0,'NA']]
 
# Create the pandas DataFrame
df_out = pd.DataFrame(data_out, columns=['rowid', 'Col1','max_matching#','Rowid'])

最大匹配数# : 解释
第1行的值 : 'AA,AC,BC,DE' 与第2行的2个值('AA'和'BC')匹配,和第3行的1个值('BC')匹配,和第4行的2个值('AA'和'BC')匹配,和第5行没有匹配(NIL)。
所以最大匹配数是所有行中的最大匹配数(即2,1,2,NA)= 2
行号 : 解释
第1行的值 : 'AA,AC,BC,DE' : 从上面的解释中得到的最大匹配行,即第2行和第4行(2,4)

提前谢谢你!

相关问题:

1 个回答

1

你可以把你的字符串转换成一个集合(set),然后计算两个行之间的相似度,方法是找出它们的交集的长度(可以借助pdist这个工具)。最后,使用groupby.agg来生成输出的列(比如计数和连接的索引):

from scipy.spatial.distance import pdist, squareform

# convert strings to sets
s = df['Col1'].apply(lambda x: set(x.split(',')))

# function to compute length of the set intersection
def compare(a, b):
    return len((a[0]&b[0]))

out = df.merge(
 pd.DataFrame(squareform(pdist(s.to_frame(), compare)),
              index=df['rowid'], columns=df['rowid'].rename('Rowid'))
   .stack().reset_index(name='count')
   .query('(rowid != Rowid) & (count > 0)')
   .groupby('rowid', as_index=False)
   #.loc[lambda d: d.groupby('rowid')['count'].transform('max').eq(d['count'])]
   .agg({'count': 'max',
         'Rowid': lambda x: ','.join(x.astype(str))
        })
    .rename(columns={'count': 'max_matching#'}),
  on='rowid', how='left'
)

# optionally fillna
out['max_matching#'] = out['max_matching#'].fillna(0).astype(int)

输出结果:

   rowid           Col1  max_matching#  Rowid
0      1    AA,AC,BC,DE              3  2,3,4
1      2     AA,AD,BC,D              2  1,3,4
2      3       A,C,BC,E              1  1,2,4
3      4  AA,AC,BC,DEEE              3  1,2,3
4      5             KK              0    NaN

如果你只想列出那些匹配次数最多的id,可以取消注释那一行.loc[lambda d: d.groupby('rowid')['count'].transform('max').eq(d['count'])]

输出结果:

   rowid           Col1  max_matching#  Rowid
0      1    AA,AC,BC,DE              3      4
1      2     AA,AD,BC,D              2    1,4
2      3       A,C,BC,E              1  1,2,4
3      4  AA,AC,BC,DEEE              3      1
4      5             KK              0    NaN

中间的交集:

pd.DataFrame(squareform(pdist(s.to_frame(), compare)),
             index=df['rowid'], columns=df['rowid'].rename('Rowid'))

Rowid  1  2  3  4  5
rowid               
1      0  2  1  3  0
2      2  0  1  2  0
3      1  1  0  1  0
4      3  2  1  0  0
5      0  0  0  0  0

撰写回答