我有一个数据框df
,如下所示:
id1 id2 weights
0 a 2a 144.0
1 a 2b 52.5
2 a 2c 2.0
3 a 2d 1.0
4 a 2e 1.0
5 b 2a 2.0
6 b 2e 1.0
7 b 2f 1.0
8 b 2b 1.0
9 b 2c 0.008
mat
列的元素之间的相似性矩阵id2
:
2a 2b 2c 2d 2e 2f
2a 1 0.5 0.7 0.2 0.1 0.3
2b 0.5 1 0.6 0.4 0.3 0.4
2c 0.7 0.6 1 0.1 0.4 0.2
2d 0.2 0.4 0.1 1 0.8 0.7
2e 0.1 0.3 0.4 0.8 1 0.8
2f 0.3 0.4 0.2 0.7 0.8 1
现在我想在id1
的元素和id2
的元素之间创建一个相似度矩阵。为此,我将id1
的元素视为id2
的相应元素的重心,我的数据框df
(带有相应的weights
)。
我的第一次尝试是使用循环(aouch):
ids = df.id1.unique()
output = pd.DataFrame(columns = mat.columns,index = ids)
for id in ids:
df_slice = df.loc[df.id1 == id]
to_normalize = df_slice.weights.sum()
temp = mat.loc[df_slice.id2]
for art in df_slice.id2:
temp.loc[art] *= df_slice.ix[df_slice.id2 == art,'weights'].values[0]
temp.loc[art] /= (1.*to_normalize)
output.loc[id] = temp.sum()
但当然这不是pythonic,并且需要很长时间(timeit
这些小矩阵显示21.3ms
不能计算10k行df
和3k乘3k {{1} }})。什么是更干净/有效的方法呢?
期望的输出:
mat
有没有办法计算 2a 2b 2c 2d 2e 2f
a 0.857606 0.630424 0.672319 0.258354 0.163342 0.329676
b 0.580192 0.540096 0.520767 0.459425 0.459904 0.559425
元素之间的另一个相似性矩阵(来自这个数据)?
提前谢谢。
答案 0 :(得分:2)
以下时钟频率为6-7毫秒(相对于我的机器所采用的时间约为30毫秒)。
import io
import pandas as pd
raw_df = io.StringIO("""\
id1 id2 weights
0 a 2a 144.0
1 a 2b 52.5
2 a 2c 2.0
3 a 2d 1.0
4 a 2e 1.0
5 b 2a 2.0
6 b 2e 1.0
7 b 2f 1.0
8 b 2b 1.0
9 b 2c 0.008
""")
df = pd.read_csv(raw_df, delim_whitespace=True)
raw_mat = io.StringIO("""\
2a 2b 2c 2d 2e 2f
2a 1 0.5 0.7 0.2 0.1 0.3
2b 0.5 1 0.6 0.4 0.3 0.4
2c 0.7 0.6 1 0.1 0.4 0.2
2d 0.2 0.4 0.1 1 0.8 0.7
2e 0.1 0.3 0.4 0.8 1 0.8
2f 0.3 0.4 0.2 0.7 0.8 1
""")
mat = pd.read_csv(raw_mat, delim_whitespace=True)
df['norm'] = df.groupby('id1')['weights'].transform('sum')
m = pd.merge(df, mat, left_on='id2', right_index=True)
m[mat.index] = m[mat.index].multiply(m['weights'] / m['norm'], axis=0)
output = m.groupby('id1')[mat.index].sum()
output.columns.name = 'id2'
print(output)
输出:
id2 2a 2b 2c 2d 2e 2f
id1
a 0.857606 0.630424 0.672319 0.258354 0.163342 0.329676
b 0.580192 0.540096 0.520767 0.459425 0.459904 0.559425