是否可以使用不同大小的 NumPy 数组对每行搜索和比较进行矢量化?

问题描述

假设我有以下两个二维数据集(Dataframes 或 Numpy Arrays):

input_data:

identifier date
A          2021-01-01
A          2018-03-12
A          2017-02-07
B          2021-01-01
C          2021-01-01
...
comparison_data:

identifier date       match_id
A          2021-01-01 1
A          2018-03-12 1
C          2021-01-01 2
...

input_data 的大小是可变的。 compare_data 是静态的;即它是一组固定的唯一标识符-日期对(数量级说 103 到 104 行)。在大多数情况下,input_data 比comparison_data 大得多,并且input_data 标识符的基数非常低(即通常只有comparison_data 标识符的一小部分出现在input_data 中)。

目标是将 input_data 的每一行与 compare_data 的 match_id 匹配,如果无法匹配该行,则回退值 0。导致匹配的具体比较是无关紧要的;为简单起见,我们假设标识符和日期必须相等。所以对于上面的数据集,结果是:

output_data:

identifier date       match_id
A          2021-01-01 1
A          2018-03-12 1
A          2017-02-07 0
B          2021-01-01 0
C          2021-01-01 2
...

使用以下列表推导式,对于 500'000 行的常见 input_data 示例,整个匹配需要约 1 秒:

input_data['match_id'] = 
[(
    matched_rows = comparison_data[comparison_data[:,identifier_index] == x]
    matched_rows = matched_rows[matched_rows[:,date_index] == y]
    if 1 == len(matched_rows):
        return matched_rows[0,match_id_index]
    return 0
)
for x,y in zip(input_data['identifier'],input_data['date'])]

这显然是伪代码;该过程在一个函数内,除其他外,我正在缓存标识符找到的第一个matched_rows(因此对于 input_data 中的每个唯一标识符,5'000 行只需要过滤一次;由于基数低,这很有效,这就是为什么我没有 &-连接标识符和日期的匹配)。

我发现 ~1 秒是这个特定案例的硬底;我尝试了使用广播、矢量化 NumPy 函数或 numba.vectorized 的不同技术,但它们都较慢,因为我一直回到不得不在某处使用列表理解来搜索或比较不同大小的数组的问题。例如,使用 input_data['identifier'].isin(comparison_data[:,identifier_index]) 过滤比较数据会使匹配下降两个数量级,但过滤器本身需要大约 5 秒。预先按标识符对数据进行分组也不比简单地缓存标识符快。

我想听听在矢量化方面有更多经验的人,以及他们可能对如何以纯矢量化的方式解决这个问题以进一步提高性能有想法的人。或者反过来说,有足够知识的人可以自信地说这是一个向量化不能比列表推导更快的问题。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)