python - 基于第二个 Numpy 数组的更快的 Numpy 数组元素分组方法
问题描述
有 2 个 NumPy 数组groups
和selectors
,其中
selectors
是一个包含需要分组的整数的数组
import numpy as np
np.random.seed(0)
selectors = np.random.randint(0, 300, 5)
# [172 47 117 192 251]
groups
是一个结构化数组,包含组 (str) 的第一个索引 (int)
# Generate groups `a` to `t` and their first index
start = ord('a')
groups = []
for i in range(20):
e = (i*i, chr(start+i))
groups.append(e)
groups = np.array(groups, dtype=[('index', np.uint32), ('selector', '|U1')])
groups = np.sort(groups, order='index')
# [( 0, 'a') ( 1, 'b') ( 4, 'c') ( 9, 'd') ( 16, 'e') ( 25, 'f')
# ( 36, 'g') ( 49, 'h') ( 64, 'i') ( 81, 'j') (100, 'k') (121, 'l')
# (144, 'm') (169, 'n') (196, 'o') (225, 'p') (256, 'q') (289, 'r')
# (324, 's') (361, 't')]
给定这些示例数组,分组后所需的结果将是np.ndarrays
/lists的字典
{
"g": [47] ,
"k": [117],
"n": [172, 192],
"p": [251]
}
有没有更快的方法在 Numpy 中执行此分组而不是嵌套 2 个循环,如下所示?这对于使用100-1000 行的selectors
数组的 10-1 亿行的大型数组很有用。groups
使用嵌套循环
results = {}
for s in selectors:
for i in range(len(groups)-1):
if s >= groups[i][0] and s < groups[i+1][0]:
j = i
break
else:
j = i + 1
try:
results[groups[j][1]].append(s)
except KeyError:
results[groups[j][1]] = [s]
print(results)
# {'n': [172, 192], 'g': [47], 'k': [117], 'p': [251]}
解决方案
如果您在每个选择器上使用二进制搜索,您实际上是在将例程的时间O(len(groups) * len(selectors))
从O(log2(len(groups)) * len(selectors))
该模块上的Python 文档bisect
解释了如何使用它来查找小于或等于指定值的最右侧元素。
推荐阅读
- redis - 有没有办法在 jedis 中传递 redis 命令,而不使用函数?
- c++ - c++ - 这会导致任何问题吗?使用将自身作为参数传递的函数分配 var(我很难解释)
- python - django python 中(POST 方法)处的 EncodeError。回复后 500
- laravel - 产品未删除
- angular - 如何更改图表中的时间格式?
- concurrency - 包装与 ConcurrentHashMap 同步
- python - 在 dask 数据框中,行与其前导之间的差异为 3 行
- amazon-web-services - 开发人员访问 AWS
- awk - 用于读取每行中具有不同字段数的输入文件的 awk 脚本
- google-cloud-datastore - 如何将数据插入数据存储区