【问题标题】:Fast mutation of ndarray (replace part of numpy ndarray)ndarray 的快速突变(替换 numpy ndarray 的一部分)
【发布时间】:2018-07-29 20:16:25
【问题描述】:

我正在寻找最快的方法来替换部分预分配的 numpy ndarray。 下面你可以看到sim_matrix(2D ndarray)。 “For 循环”迭代它rowwise 并覆盖levels (numpy.array) 给出的值。

有快速的方法,找到了:

  1. numpy.copyto()
  2. numpy.fromiter()
  3. = 分配给切片

注意:为简单起见,我在每次迭代中分配相同的值,但在生产设置中并非如此。在实际设置中,levels 每行包含不同的值。因此,不鼓励将快捷方式用作numpy.repeatnumpy.hstack 作为答案。

有没有更快的方法来更改 ndarray 的某些部分?

numpy_overwrite.py:

import numpy
panel_size = 365 * 7
rows = 1 * (1+1+2*4) * 10000
# rows = 100
levels = [1778.24] * panel_size
levels_array = numpy.fromiter(levels,dtype='single', count = len(levels))
sim_matrix = numpy.empty([rows, panel_size],dtype='single')

def _copyto(sim_matrix_, level_):
    for i in range(sim_matrix_.shape[0]):
        numpy.copyto(sim_matrix[i], level_)


def _fromiter(sim_matrix_, level_):
    len_level = len(level_)
    for i in range(sim_matrix_.shape[0]):
        sim_matrix[i] = numpy.fromiter(level_,
                                      dtype='single', 
                                      count = len_level)

def _just_assign(sim_matrix_, level_):
    for i in range(sim_matrix_.shape[0]):
        sim_matrix[i] = level_

numpy_overwrite_test.py

import timeit
import numpy_overwrite as npo
print('_fromiter')
print(timeit.timeit('npo._fromiter(npo.sim_matrix, npo.levels)', setup="import numpy_overwrite as npo;", number=3))
print(timeit.timeit('npo._fromiter(npo.sim_matrix, npo.levels_array)', setup="import numpy_overwrite as npo;", number=3))
print('_copyto')
print(timeit.timeit('npo._copyto(npo.sim_matrix, npo.levels)', setup="import numpy_overwrite as npo;", number=3))
print(timeit.timeit('npo._copyto(npo.sim_matrix, npo.levels_array)', setup="import numpy_overwrite as npo;", number=3))
print('_just_assign')
print(timeit.timeit('npo._just_assign(npo.sim_matrix, npo.levels)', setup="import numpy_overwrite as npo;", number=3))
print(timeit.timeit('npo._just_assign(npo.sim_matrix, npo.levels_array)', setup="import numpy_overwrite as npo;", number=3))

运行测试

_fromiter
=========
from python list: 21.129429172957316
from numpy.array: 61.76275303697912

_copyto
=========
from python list: 52.4522930260282
from numpy.array: 0.7605530479922891

_just_assign
=========
from python list: 52.251478374004364
from numpy.array: 0.6351132979616523
    

【问题讨论】:

  • 我不认为pass 关键字在这里有用
  • @nicoco 我用它们来直观地指示块的结束,删除它们。
  • 我认为如果你使用 levels 实际上确实有不同的值会更好。也许是随机分布的?
  • @Graipher 然后在每次迭代中都会产生伪数生成器的开销。
  • 不在你的函数调用中,在你准备测试数据时。就目前而言,我不明白为什么@nicoco 的建议应该是错误的。您可以在每次调用时将不同的级别传递给函数。

标签: python numpy


【解决方案1】:

您可能只是在寻找这个吗?

sim_matrix[:] = levels

EDIT:要修改一行,应该使用sim_matrix[row_id] = levels

另外,请注意using mutables as default function arguments

【讨论】:

  • 不,levels 的值会因每次调用而不同。
  • 这些levels 是从哪里来的?一份清单?
  • 如果要更改单行,只需使用sim_matrix[row] = levels
  • @CronMerdek 我试图找出您的真实用例是什么样的。因为取决于此,可能会有更快的选项(例如,如果您拥有所有级别,则一次覆盖多行)。
  • @Graipher 我添加了赋值调用示例
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-10
  • 2021-10-15
  • 2018-06-05
  • 1970-01-01
  • 1970-01-01
  • 2017-09-08
相关资源
最近更新 更多