【发布时间】:2023-03-20 12:05:01
【问题描述】:
假设以下简化框架:
我有一个由 100 行、4 个类和每个实例的 4 个特征组成的参数的 3D Pandas 数据框:
iterables = [list(range(100)), [0,1,2,3]]
index = pd.MultiIndex.from_product(iterables, names=['instances', 'classes'])
columns = ['a', 'b', 'c', 'd']
np.random.seed(42)
parameters = pd.DataFrame(np.random.randint(1, 2000, size=(len(index), len(columns))), index=index, columns=columns)
parameters
instances classes a b c d
0 0 1127 1460 861 1295
1 1131 1096 1725 1045
2 1639 122 467 1239
3 331 1483 88 1397
1 0 1124 872 1688 131
... ... ... ... ...
98 3 1321 1750 779 1431
99 0 1793 814 1637 1429
1 1370 1646 420 1206
2 983 825 1025 1855
3 1974 567 371 936
让df 成为一个数据框,为每个实例和每个特征(列)报告观察到的类。
np.random.seed(42)
df = pd.DataFrame(np.random.randint(0, 3, size=(100, len(columns))), index=list(range(100)),
columns=columns)
a b c d
0 2 0 2 2
1 0 0 2 1
2 2 2 2 2
3 0 2 1 0
4 1 1 1 1
.. .. .. .. ..
95 1 2 0 1
96 2 1 2 1
97 0 0 1 2
98 0 0 0 1
99 1 2 2 2
我想根据数据框 df 上观察到的类创建第三个形状为 (100, 4) 的数据框(我们称之为 new_df),其中包含数据框 parameters 中的参数。
例如,在df的第一行第一列(a)我观察到类2,所以我感兴趣的值是parameters数据框的第一个实例中的第二个类,即1127 将填充new df 的第一行和第一列。按照这种方法,“b”列的第一个观察是0类,所以在第一行,new_df的b列我想观察1460等等。
使用 for 循环我可以获得想要的结果:
new_df = pd.DataFrame(0, index=list(range(100)), columns=columns) # initialize the df
for i in range(len(df)):
for c in df.columns:
new_df.iloc[i][c] = parameters.loc[i][c][df.iloc[i][c]]
new_df
a b c d
0 1639 1460 467 1239
1 1124 872 806 344
2 1083 511 1706 1500
3 958 1155 1268 563
4 14 242 777 1370
.. ... ... ... ...
95 1435 1316 1709 755
96 346 712 363 815
97 1234 985 683 1348
98 127 1130 1009 1014
99 1370 825 1025 1855
但是,原始数据集包含数百万行和数百列,继续进行 for 循环是不可行的。
有没有办法对这样的问题进行矢量化以避免 for 循环? (至少超过 1 个维度)
【问题讨论】:
标签: python pandas for-loop vectorization