【发布时间】:2021-12-31 14:20:17
【问题描述】:
我正在努力对使用 pandas 查找表的代码进行矢量化,其中索引由第一个数组中的值选择,列由第二个数组中的值选择。
假设我有两个 numpy 数组 a 和 b(它们的形状相同):
codes = np.random.randint(1000, size=(4))
a_idx = np.random.randint(4, size=(6, 6))
a = codes[a_idx]
a[2, 1] = -999
a
Out[267]:
array([[ 310, 310, 52, 310, 218, 310],
[ 687, 310, 218, 310, 687, 687],
[ 218, -999, 310, 218, 52, 687],
[ 218, 218, 687, 52, 687, 310],
[ 52, 687, 687, 52, 687, 218],
[ 52, 218, 52, 687, 310, 52]])
b = np.random.randint(5, size=(6, 6))
b
Out[269]:
array([[2, 4, 3, 2, 0, 4],
[2, 4, 4, 2, 1, 0],
[0, 0, 1, 1, 2, 0],
[2, 2, 2, 2, 2, 1],
[4, 1, 3, 1, 1, 2],
[0, 3, 2, 2, 3, 0]])
我还有一个 pandas 查找表:
lookup = pd.DataFrame({'A': np.arange(1, 5),
'B': np.arange(11, 15),
'C': np.arange(21, 25)}, index=codes)
lookup.loc[-999] = 0
lookup
Out[275]:
A B C
310 1 11 21
687 2 12 22
218 3 13 23
52 4 14 24
-999 0 0 0
我已经为 pandas 列名创建了一个字典(不同的数字可以有相同的字母):
b_dict = {0: 'A', 1: 'B', 2: 'C', 3: 'B', 4:'A'}
我想从查找表中创建第三个数组,其中索引由数组a 中的值选择,列从数组b 中选择(在b_dict 的帮助下)。
这就是嵌套 for 循环的方式:
res = np.empty_like(a)
for i, (row_a, row_b) in enumerate(zip(a, b)):
for j, (aij, bij) in enumerate(zip(row_a, row_b)):
res[i, j] = lookup.loc[aij, b_dict[bij]]
这将是期望的结果:
res
Out[276]:
array([[21, 1, 14, 21, 3, 1],
[22, 1, 3, 21, 12, 2],
[ 3, 0, 11, 13, 24, 2],
[23, 23, 22, 24, 22, 11],
[ 4, 12, 12, 14, 12, 23],
[ 4, 13, 24, 22, 11, 4]])
对于使用 numpy 或 pandas 的大型数组,是否有更快(矢量化)的方法,我想避免嵌套循环?
编辑:我将示例更改为更接近实际问题。
【问题讨论】:
-
你应该可以只做
lookup.values[a, b]。您可以搜索 numpy 高级索引以获取更多信息。 -
@Psidom 你的回答可以帮助 OP,并可能为他指明未来相关场景的正确方向
-
@Psidom,谢谢你的建议,看来我给的例子太简单了。不幸的是,我的实际数据对于简单的索引来说太复杂了。查找表的索引不是序数而是整数代码,查找表索引看起来更像
2, 156, 45, 893, 17,...。数组a和b也有nan值,我将其替换为单个负值... -
@NinoKrvavica 然后请使用该信息和更接近真实场景的稍微复杂的示例更新问题。我们可以假设
a、b和lookup具有相同的形状,对吧? -
@HarryPlotter,谢谢,我更新了示例,
a和b形状相同,但lookup形状不同。
标签: python arrays pandas dataframe numpy