将 pandas MultiIndex (k x n x n) 乘以 DataFrame (k x n x 1)
Multiply a pandas MultiIndex (k x n x n) by a DataFrame (k x n x 1)
我有一个时间序列的协方差矩阵存储为 MultiIndex(我们称之为“A”)和一个时间序列的标量存储为 DataFrame(我们称之为“b”)。
“A”的形状为“k”x“n”x“n”,“b”的形状为“k”x“n”,所以我有协方差矩阵的“k”个日期的 MultiIndex形状为“n”x“n”,我想乘以标量的“k”x“n”x 1 DataFrame以获得“k”x“n”x 1 DataFrame。
当我尝试类似 A.multiply(b) 的操作时,它不起作用,因为 MultiIndex 维度是 (kxn, n) 并且不严格匹配 (k, n) 的 DataFrame 维度。
我能够使用列表理解来执行计算并将 MultiIndex 和 DataFrame 转换为 numpy 数组,但这需要非常非常长的时间,所以我的效率肯定很低。
这方面的一个例子是:
[np.dot( np.array( A.loc[timestamp,:] ), np.array( b.loc[timestamp,:] ) ) for timestamp in b.index]
这需要非常长的时间来计算。有没有快速的方法来执行此计算?
这是大小为 A
5×3×3 和 b
5×3 的随机值数据帧:
>>> A
0 1 2
2021-08-14 11:14:00 0 0.309559 0.286455 0.080467
1 0.996128 0.666138 0.354322
2 0.113316 0.208389 0.197855
2021-08-14 11:15:00 0 0.299459 0.650561 0.481504
1 0.570308 0.298572 0.677013
2 0.476066 0.610945 0.750575
2021-08-14 11:16:00 0 0.861801 0.692752 0.046450
1 0.587891 0.389874 0.779039
2 0.009947 0.647356 0.735746
2021-08-14 11:17:00 0 0.990027 0.185747 0.286276
1 0.831238 0.474372 0.459076
2 0.885953 0.768626 0.866064
2021-08-14 11:18:00 0 0.952294 0.106072 0.477348
1 0.370116 0.646081 0.873394
2 0.439066 0.568404 0.227528
>>> b
0 1 2
2021-08-14 11:14:00 0.113316 0.208389 0.197855
2021-08-14 11:15:00 0.476066 0.610945 0.750575
2021-08-14 11:16:00 0.009947 0.647356 0.735746
2021-08-14 11:17:00 0.885953 0.768626 0.866064
2021-08-14 11:18:00 0.439066 0.568404 0.227528
如果要将 A
中的每一行乘以 b
的单个值,即 b
列应与 A
索引的第二级对齐, 你应该使用 stack
:
>>> A.mul(b.stack(), axis='index')
0 1 2
2021-08-14 11:14:00 0 0.035078 0.032460 0.009118
1 0.207582 0.138816 0.073837
2 0.022420 0.041231 0.039147
2021-08-14 11:15:00 0 0.142562 0.309710 0.229227
1 0.348427 0.182411 0.413618
2 0.357323 0.458560 0.563363
2021-08-14 11:16:00 0 0.008572 0.006891 0.000462
1 0.380575 0.252387 0.504315
2 0.007318 0.476290 0.541322
2021-08-14 11:17:00 0 0.877118 0.164563 0.253627
1 0.638911 0.364615 0.352858
2 0.767292 0.665679 0.750067
2021-08-14 11:18:00 0 0.418120 0.046573 0.209587
1 0.210376 0.367235 0.496441
2 0.099900 0.129328 0.051769
另一方面,如果您希望 b
列与 A
列对齐,您可以使用 pd.DataFrame.align()
,两者的 returns 对齐版本数据框。这里 A
将保持不变,如 .compare()
所确认,并且 b_aligned
将在每个二级索引中重复其行以匹配 A
的索引:
>>> b_aligned, A_aligned = b.align(A, level=0)
>>> A_aligned.compare(A)
Empty DataFrame
Columns: []
Index: []
>>> b_aligned
0 1 2
2021-08-14 11:14:00 0 0.113316 0.208389 0.197855
1 0.113316 0.208389 0.197855
2 0.113316 0.208389 0.197855
2021-08-14 11:15:00 0 0.476066 0.610945 0.750575
1 0.476066 0.610945 0.750575
2 0.476066 0.610945 0.750575
2021-08-14 11:16:00 0 0.009947 0.647356 0.735746
1 0.009947 0.647356 0.735746
2 0.009947 0.647356 0.735746
2021-08-14 11:17:00 0 0.885953 0.768626 0.866064
1 0.885953 0.768626 0.866064
2 0.885953 0.768626 0.866064
2021-08-14 11:18:00 0 0.439066 0.568404 0.227528
1 0.439066 0.568404 0.227528
2 0.439066 0.568404 0.227528
>>> A_aligned.mul(b_aligned)
0 1 2
2021-08-14 11:14:00 0 0.035078 0.059694 0.015921
1 0.112877 0.138816 0.070104
2 0.012840 0.043426 0.039147
2021-08-14 11:15:00 0 0.142562 0.397457 0.361405
1 0.271504 0.182411 0.508149
2 0.226639 0.373254 0.563363
2021-08-14 11:16:00 0 0.008572 0.448457 0.034176
1 0.005848 0.252387 0.573175
2 0.000099 0.419070 0.541322
2021-08-14 11:17:00 0 0.877118 0.142770 0.247933
1 0.736438 0.364615 0.397589
2 0.784913 0.590785 0.750067
2021-08-14 11:18:00 0 0.418120 0.060292 0.108610
1 0.162505 0.367235 0.198722
2 0.192779 0.323083 0.051769
我只是猜测你真正在做什么,因为你没有指定轴等,但这给出了与你的代码相同的结果:
>>> A.mul(b.align(A, level=0)[0]).sum(axis='columns').unstack(1)
0 1 2
2021-08-14 11:14:00 0.110693 0.321797 0.095413
2021-08-14 11:15:00 0.901424 0.962065 1.163256
2021-08-14 11:16:00 0.491205 0.831409 0.960491
2021-08-14 11:17:00 1.267821 1.498642 2.125765
2021-08-14 11:18:00 0.587022 0.728462 0.567631
我有一个时间序列的协方差矩阵存储为 MultiIndex(我们称之为“A”)和一个时间序列的标量存储为 DataFrame(我们称之为“b”)。
“A”的形状为“k”x“n”x“n”,“b”的形状为“k”x“n”,所以我有协方差矩阵的“k”个日期的 MultiIndex形状为“n”x“n”,我想乘以标量的“k”x“n”x 1 DataFrame以获得“k”x“n”x 1 DataFrame。
当我尝试类似 A.multiply(b) 的操作时,它不起作用,因为 MultiIndex 维度是 (kxn, n) 并且不严格匹配 (k, n) 的 DataFrame 维度。
我能够使用列表理解来执行计算并将 MultiIndex 和 DataFrame 转换为 numpy 数组,但这需要非常非常长的时间,所以我的效率肯定很低。
这方面的一个例子是:
[np.dot( np.array( A.loc[timestamp,:] ), np.array( b.loc[timestamp,:] ) ) for timestamp in b.index]
这需要非常长的时间来计算。有没有快速的方法来执行此计算?
这是大小为 A
5×3×3 和 b
5×3 的随机值数据帧:
>>> A
0 1 2
2021-08-14 11:14:00 0 0.309559 0.286455 0.080467
1 0.996128 0.666138 0.354322
2 0.113316 0.208389 0.197855
2021-08-14 11:15:00 0 0.299459 0.650561 0.481504
1 0.570308 0.298572 0.677013
2 0.476066 0.610945 0.750575
2021-08-14 11:16:00 0 0.861801 0.692752 0.046450
1 0.587891 0.389874 0.779039
2 0.009947 0.647356 0.735746
2021-08-14 11:17:00 0 0.990027 0.185747 0.286276
1 0.831238 0.474372 0.459076
2 0.885953 0.768626 0.866064
2021-08-14 11:18:00 0 0.952294 0.106072 0.477348
1 0.370116 0.646081 0.873394
2 0.439066 0.568404 0.227528
>>> b
0 1 2
2021-08-14 11:14:00 0.113316 0.208389 0.197855
2021-08-14 11:15:00 0.476066 0.610945 0.750575
2021-08-14 11:16:00 0.009947 0.647356 0.735746
2021-08-14 11:17:00 0.885953 0.768626 0.866064
2021-08-14 11:18:00 0.439066 0.568404 0.227528
如果要将 A
中的每一行乘以 b
的单个值,即 b
列应与 A
索引的第二级对齐, 你应该使用 stack
:
>>> A.mul(b.stack(), axis='index')
0 1 2
2021-08-14 11:14:00 0 0.035078 0.032460 0.009118
1 0.207582 0.138816 0.073837
2 0.022420 0.041231 0.039147
2021-08-14 11:15:00 0 0.142562 0.309710 0.229227
1 0.348427 0.182411 0.413618
2 0.357323 0.458560 0.563363
2021-08-14 11:16:00 0 0.008572 0.006891 0.000462
1 0.380575 0.252387 0.504315
2 0.007318 0.476290 0.541322
2021-08-14 11:17:00 0 0.877118 0.164563 0.253627
1 0.638911 0.364615 0.352858
2 0.767292 0.665679 0.750067
2021-08-14 11:18:00 0 0.418120 0.046573 0.209587
1 0.210376 0.367235 0.496441
2 0.099900 0.129328 0.051769
另一方面,如果您希望 b
列与 A
列对齐,您可以使用 pd.DataFrame.align()
,两者的 returns 对齐版本数据框。这里 A
将保持不变,如 .compare()
所确认,并且 b_aligned
将在每个二级索引中重复其行以匹配 A
的索引:
>>> b_aligned, A_aligned = b.align(A, level=0)
>>> A_aligned.compare(A)
Empty DataFrame
Columns: []
Index: []
>>> b_aligned
0 1 2
2021-08-14 11:14:00 0 0.113316 0.208389 0.197855
1 0.113316 0.208389 0.197855
2 0.113316 0.208389 0.197855
2021-08-14 11:15:00 0 0.476066 0.610945 0.750575
1 0.476066 0.610945 0.750575
2 0.476066 0.610945 0.750575
2021-08-14 11:16:00 0 0.009947 0.647356 0.735746
1 0.009947 0.647356 0.735746
2 0.009947 0.647356 0.735746
2021-08-14 11:17:00 0 0.885953 0.768626 0.866064
1 0.885953 0.768626 0.866064
2 0.885953 0.768626 0.866064
2021-08-14 11:18:00 0 0.439066 0.568404 0.227528
1 0.439066 0.568404 0.227528
2 0.439066 0.568404 0.227528
>>> A_aligned.mul(b_aligned)
0 1 2
2021-08-14 11:14:00 0 0.035078 0.059694 0.015921
1 0.112877 0.138816 0.070104
2 0.012840 0.043426 0.039147
2021-08-14 11:15:00 0 0.142562 0.397457 0.361405
1 0.271504 0.182411 0.508149
2 0.226639 0.373254 0.563363
2021-08-14 11:16:00 0 0.008572 0.448457 0.034176
1 0.005848 0.252387 0.573175
2 0.000099 0.419070 0.541322
2021-08-14 11:17:00 0 0.877118 0.142770 0.247933
1 0.736438 0.364615 0.397589
2 0.784913 0.590785 0.750067
2021-08-14 11:18:00 0 0.418120 0.060292 0.108610
1 0.162505 0.367235 0.198722
2 0.192779 0.323083 0.051769
我只是猜测你真正在做什么,因为你没有指定轴等,但这给出了与你的代码相同的结果:
>>> A.mul(b.align(A, level=0)[0]).sum(axis='columns').unstack(1)
0 1 2
2021-08-14 11:14:00 0.110693 0.321797 0.095413
2021-08-14 11:15:00 0.901424 0.962065 1.163256
2021-08-14 11:16:00 0.491205 0.831409 0.960491
2021-08-14 11:17:00 1.267821 1.498642 2.125765
2021-08-14 11:18:00 0.587022 0.728462 0.567631