使用切片对numpy数组进行赋值

10
如果b是一个2x2的np.ndarray并执行以下赋值操作,那么numpy在后台会做什么,即它是否将列表[100, 100] 首先转换为numpy数组,还是直接使用列表[100, 100]来填充b的第一行的值:
 b[1,:] = [100,100]

在文档中我可以在哪里找到更多关于此事的信息?


numpy是开源的,如果你对某个实现方式感兴趣,只需查看源代码即可。 - Bakuriu
2
答案是“这取决于情况”。请查看Numpy分发中的core/src/multiarray/sequence.carray_assign_slice:https://github.com/numpy/numpy/blob/master/numpy/core/src/multiarray/sequence.c#L91)。在您的示例中,我认为代码不会将列表转换为数组,但根据其他情况可能会。 - Alok Singhal
@goncalopp 是的,我关注内存使用情况。 - methane
9
我知道这点,但我在stackoverflow上询问,以便有人已经研究过。否则,任何与Python相关的问题都可以通过查看源代码来回答,因此你可能认为这里不需要Python标签? - methane
@AlokSinghal 谢谢!你知道有没有任何情况/例子可以证明这种可能性吗? - methane
2
@methane 我不确定——你可以查看代码,但是从快速阅读来看,似乎只有当目标维度大于源维度时才会创建一个numpy数组:例如a = numpy.empty((2,3)); a[:] = range(3)。我可能错了。 - Alok Singhal
2个回答

3
为了评估执行速度,我们将使用 timeit 库。
import timeit
import numpy as np

setup = """
import numpy as np
tmp = np.empty(shape=(1, 100))
values = [i for i in xrange(100)]
"""

stmt1 = """tmp[0, :] = values"""
stmt2 = """
for i, val in enumerate(values):
    tmp[0, i] = val
"""

time1 = timeit.Timer(setup=setup, stmt=stmt1)
time2 = timeit.Timer(setup=setup, stmt=stmt2)

print "numpy way :", time1.timeit(number=100000)
print "Python way:", time2.timeit(number=100000)

您可以测试一下,您会注意到numpy循环速度快了两倍:
- numpy way : 0.97758197784423828
- Python way: 2.1633858680725098

这是因为在 values 中的整数(它们是无限整数)被转换成 64 位浮点数的阶段。为了仅比较循环的速度,类型转换可以在设置中预先完成:

values = np.array([i for i in xrange(100)], dtype=np.float64)

这是我得到的内容:
numpy way : 0.131125926971
Python way: 2.64055013657

我们注意到numpy循环比Python循环快20倍。如果您寻找有关Python中向量化计算的更多信息,请查看此链接

-2

b[1,:] = [100,100]

是完全相同的。
b[1,0] = 100
b[1,1] = 100

然而,由于它使用编译循环,因此执行速度更快。 (第二个需要在分配值之前将其转换为ndarray dtype)。


1
这个在文档中有提到吗?如果有的话,能否请提供一下相关链接?谢谢。 - DJG
请告诉我,如果文档中有相关信息的话。什么是编译循环? - methane
你好, 我正在谈论解释语言和编译语言之间的区别。众所周知,Python可以逐个命令地执行,而C或Java则需要编译。 众所周知,numpy是一种与Python配合使用但作为编译程序运行的接口。下面的答案中给出了关于循环性能的一个例子。 - Taha

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接