从 pandas 中的数据框和矩阵创建新矩阵
Creating new matrix from dataframe and matrix in pandas
我有一个数据框 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
以及id2
列元素之间的相似度矩阵mat
:
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
ind 我的数据帧 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 x 3k mat
).更 clean/efficient 的方法是什么?
期望的输出:
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
有没有办法计算 id1
的元素之间的另一个相似性矩阵(根据此数据)?
提前谢谢你。
以下时钟为 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
我有一个数据框 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
以及id2
列元素之间的相似度矩阵mat
:
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
ind 我的数据帧 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 x 3k mat
).更 clean/efficient 的方法是什么?
期望的输出:
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
有没有办法计算 id1
的元素之间的另一个相似性矩阵(根据此数据)?
提前谢谢你。
以下时钟为 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