通过遍历同一列的行比较并找到最接近的匹配字符串
我刚开始学习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