与 numpy repeat 一起使用的两个数组的逐元素编织
Element-wise weave of two arrays used with numpy repeat
我有两个长度不等的数组 val1 和 val2 我试图以特定的方式编织在一起等长数组 mult1 和 mult2。一般来说,我的数组很长(~1e6 个元素),这是我计算中的性能关键瓶颈,所以我无法承受 python-for 循环,所以我试图利用Numpy 中的向量化函数。为了明确起见:
mult1 = np.array([0, 1, 2, 1, 0])
mult2 = np.array([1, 0, 1, 1, 0])
val1 = np.array([1, 2, 3, 4])
val2 = np.array([-1, -2, -3])
desired_final_result = np.array([-1, 1, 2, 3, -2, 4, -3])
val1 和 val2 的编织由以下通过 mult1 的索引的逐元素处理定义 和 mult2。两个 mult 数组的每个条目定义了从相应的 val 数组中选择多少个元素。我们通过 mult 数组逐元素进行; mult1[i] 的值决定了我们从 val1 中选择了多少条目,然后我们继续 mult2[ 的值i] 到 select 适当数量的 val2 条目,始终选择 val1 条目首先出现指数一。
注意 len(val1) = mult1.sum() 和 len(val2) = mult2.sum(),所以我们总是以 len(desired_final_result) = len(val1) + len(val2) 最终数组结束。
最小示例的明确解释
因为 mult1 的条目 i=0 是 0,我们 select 0 来自 val1 的条目,然后继续 i=0 的条目 mult2,即 1,所以我们 select 1 来自 val2。这解释了为什么 desired_final_result 的第一个条目是 -1。
因为 mult1 的条目 i=1 是 1,我们 select 1 来自 val1 的条目,然后继续 i=1 的条目 mult2,即 0,因此 select 0 来自 val2 的条目。这就解释了为什么 desired_final_result 的第二个条目是 1。
因为 mult1 的条目 i=2 是 2,我们 select 来自 val1 的下一个 2 个条目,然后继续条目 i=2 mult2,即 1,因此我们 select 下一个 1 条目来自 val2。这解释了为什么 desired_final_result 的条目 2-4 是 2、3、-2。
因为 mult1 的条目 i=3 是 1,我们 select 来自 val1 的下一个 1 条目,然后继续进入条目 i=3 mult2,也是 1,所以我们 select 下一个 1 条目来自val2。这解释了为什么 desired_final_result 的条目 5-6 是 4, -3。
最后,由于 i=4 mult1 和 mult2 是 0,我们无事可做,我们的数组已填满。
问题
有没有办法使用矢量化函数,例如np.repeatand/ornp.choose解决我的问题?或者我是否需要求助于用 C 编写此计算并将其包装到 python?
这可以通过 NumPy 例程来完成,但我想出的最好的方法非常笨拙:
reps = numpy.empty([len(mult1)*2], dtype=int)
reps[::2] = mult1
reps[1::2] = mult2
to_repeat = numpy.empty_like(reps)
to_repeat[::2] = -1 # Avoid using 0 and 1 in case either of val1 or val2 is empty
to_repeat[1::2] = -2
indices = numpy.repeat(to_repeat, reps)
indices[indices==-1] = numpy.arange(len(val1))
indices[indices==-2] = numpy.arange(len(val1), len(val1) + len(val2))
final_result = numpy.concatenate([val1, val2])[indices]
正在为结果数组创建布尔索引:
mult = np.array([mult1, mult2]).ravel('F')
tftf = np.tile([True, False], len(mult1))
mask = np.repeat(tftf, mult)
result = np.empty(len(val1) + len(val2), int)
result[ mask] = val1
result[~mask] = val2
编辑 - 我相信这也有效:
idx = np.repeat(mult1.cumsum(), mult2)
result = np.insert(val1, idx, val2)
它很短,但可能不会更快。
我有两个长度不等的数组 val1 和 val2 我试图以特定的方式编织在一起等长数组 mult1 和 mult2。一般来说,我的数组很长(~1e6 个元素),这是我计算中的性能关键瓶颈,所以我无法承受 python-for 循环,所以我试图利用Numpy 中的向量化函数。为了明确起见:
mult1 = np.array([0, 1, 2, 1, 0])
mult2 = np.array([1, 0, 1, 1, 0])
val1 = np.array([1, 2, 3, 4])
val2 = np.array([-1, -2, -3])
desired_final_result = np.array([-1, 1, 2, 3, -2, 4, -3])
val1 和 val2 的编织由以下通过 mult1 的索引的逐元素处理定义 和 mult2。两个 mult 数组的每个条目定义了从相应的 val 数组中选择多少个元素。我们通过 mult 数组逐元素进行; mult1[i] 的值决定了我们从 val1 中选择了多少条目,然后我们继续 mult2[ 的值i] 到 select 适当数量的 val2 条目,始终选择 val1 条目首先出现指数一。
注意 len(val1) = mult1.sum() 和 len(val2) = mult2.sum(),所以我们总是以 len(desired_final_result) = len(val1) + len(val2) 最终数组结束。
最小示例的明确解释
因为 mult1 的条目 i=0 是 0,我们 select 0 来自 val1 的条目,然后继续 i=0 的条目 mult2,即 1,所以我们 select 1 来自 val2。这解释了为什么 desired_final_result 的第一个条目是 -1。
因为 mult1 的条目 i=1 是 1,我们 select 1 来自 val1 的条目,然后继续 i=1 的条目 mult2,即 0,因此 select 0 来自 val2 的条目。这就解释了为什么 desired_final_result 的第二个条目是 1。
因为 mult1 的条目 i=2 是 2,我们 select 来自 val1 的下一个 2 个条目,然后继续条目 i=2 mult2,即 1,因此我们 select 下一个 1 条目来自 val2。这解释了为什么 desired_final_result 的条目 2-4 是 2、3、-2。
因为 mult1 的条目 i=3 是 1,我们 select 来自 val1 的下一个 1 条目,然后继续进入条目 i=3 mult2,也是 1,所以我们 select 下一个 1 条目来自val2。这解释了为什么 desired_final_result 的条目 5-6 是 4, -3。
最后,由于 i=4 mult1 和 mult2 是 0,我们无事可做,我们的数组已填满。
问题
有没有办法使用矢量化函数,例如np.repeatand/ornp.choose解决我的问题?或者我是否需要求助于用 C 编写此计算并将其包装到 python?
这可以通过 NumPy 例程来完成,但我想出的最好的方法非常笨拙:
reps = numpy.empty([len(mult1)*2], dtype=int)
reps[::2] = mult1
reps[1::2] = mult2
to_repeat = numpy.empty_like(reps)
to_repeat[::2] = -1 # Avoid using 0 and 1 in case either of val1 or val2 is empty
to_repeat[1::2] = -2
indices = numpy.repeat(to_repeat, reps)
indices[indices==-1] = numpy.arange(len(val1))
indices[indices==-2] = numpy.arange(len(val1), len(val1) + len(val2))
final_result = numpy.concatenate([val1, val2])[indices]
正在为结果数组创建布尔索引:
mult = np.array([mult1, mult2]).ravel('F')
tftf = np.tile([True, False], len(mult1))
mask = np.repeat(tftf, mult)
result = np.empty(len(val1) + len(val2), int)
result[ mask] = val1
result[~mask] = val2
编辑 - 我相信这也有效:
idx = np.repeat(mult1.cumsum(), mult2)
result = np.insert(val1, idx, val2)
它很短,但可能不会更快。