pd.Series 到 pd.DataFrame 同时将每个元素与其他元素相乘
pd.Series to pd.DataFrame while multiplying each element with each other element
假设我有一个 | a | b | c | d |
形式的向量,例如
vec = pd.Series([0.3,0.2,0.2,0.3])
构建 pd.DataFrame
形式的快速而优雅的方法是什么:
| a*a | a*b | a*c | a*d |
| b*a | b*b | b*c | b*d |
| c*a | c*b | c*c | c*d |
| d*a | d*b | d*c | d*d |
使用 numpy 广播:
vec = pd.Series([0.3,0.2,0.2,0.3])
a = vec.to_numpy()
df = pd.DataFrame(a * a[:, None], index=vec.index, columns=vec.index)
print (df)
0 1 2 3
0 0.09 0.06 0.06 0.09
1 0.06 0.04 0.04 0.06
2 0.06 0.04 0.04 0.06
3 0.09 0.06 0.06 0.09
df = pd.DataFrame(np.outer(vec, vec), index=vec.index, columns=vec.index)
print (df)
0 1 2 3
0 0.09 0.06 0.06 0.09
1 0.06 0.04 0.04 0.06
2 0.06 0.04 0.04 0.06
3 0.09 0.06 0.06 0.09
性能(如果像评论中提到的@enke 一样重要):
np.random.seed(2022)
vec = pd.Series(np.random.rand(10000))
print (vec)
In [39]: %%timeit
...: fr = vec.to_frame()
...: out = fr.dot(fr.T)
...:
386 ms ± 13.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [40]: %%timeit
...: pd.DataFrame(np.outer(vec, vec), index=vec.index, columns=vec.index)
...:
...:
351 ms ± 2.62 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [41]: %%timeit
...: a = vec.to_numpy()
...:
...: df = pd.DataFrame(a * a[:, None], index=vec.index, columns=vec.index)
...:
293 ms ± 4.22 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
一种选择是使用 dot
:
fr = vec.to_frame()
out = fr.dot(fr.T)
输出:
0 1 2 3
0 0.09 0.06 0.06 0.09
1 0.06 0.04 0.04 0.06
2 0.06 0.04 0.04 0.06
3 0.09 0.06 0.06 0.09
假设我有一个 | a | b | c | d |
形式的向量,例如
vec = pd.Series([0.3,0.2,0.2,0.3])
构建 pd.DataFrame
形式的快速而优雅的方法是什么:
| a*a | a*b | a*c | a*d |
| b*a | b*b | b*c | b*d |
| c*a | c*b | c*c | c*d |
| d*a | d*b | d*c | d*d |
使用 numpy 广播:
vec = pd.Series([0.3,0.2,0.2,0.3])
a = vec.to_numpy()
df = pd.DataFrame(a * a[:, None], index=vec.index, columns=vec.index)
print (df)
0 1 2 3
0 0.09 0.06 0.06 0.09
1 0.06 0.04 0.04 0.06
2 0.06 0.04 0.04 0.06
3 0.09 0.06 0.06 0.09
df = pd.DataFrame(np.outer(vec, vec), index=vec.index, columns=vec.index)
print (df)
0 1 2 3
0 0.09 0.06 0.06 0.09
1 0.06 0.04 0.04 0.06
2 0.06 0.04 0.04 0.06
3 0.09 0.06 0.06 0.09
性能(如果像评论中提到的@enke 一样重要):
np.random.seed(2022)
vec = pd.Series(np.random.rand(10000))
print (vec)
In [39]: %%timeit
...: fr = vec.to_frame()
...: out = fr.dot(fr.T)
...:
386 ms ± 13.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [40]: %%timeit
...: pd.DataFrame(np.outer(vec, vec), index=vec.index, columns=vec.index)
...:
...:
351 ms ± 2.62 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [41]: %%timeit
...: a = vec.to_numpy()
...:
...: df = pd.DataFrame(a * a[:, None], index=vec.index, columns=vec.index)
...:
293 ms ± 4.22 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
一种选择是使用 dot
:
fr = vec.to_frame()
out = fr.dot(fr.T)
输出:
0 1 2 3
0 0.09 0.06 0.06 0.09
1 0.06 0.04 0.04 0.06
2 0.06 0.04 0.04 0.06
3 0.09 0.06 0.06 0.09