代码之家  ›  专栏  ›  技术社区  ›  John Zwinck

NumPy:使用自身修改数组时出现错误结果

  •  4
  • John Zwinck  · 技术社区  · 10 年前
    import numpy as np
    bc = np.arange(10) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    # regular way using NumPy function
    np.diff(bc) # array([1, 1, 1, 1, 1, 1, 1, 1, 1])
    
    # something similar with array subtraction:
    bc[1:] - bc[:-1] # array([1, 1, 1, 1, 1, 1, 1, 1, 1])
    
    # but this does the wrong thing:
    bc[1:] -= bc[:-1] # array([0, 1, 1, 2, 2, 3, 3, 4, 4, 5])
    

    作为一名C和C++程序员,我可以理解为什么会发生这种情况(它是memcpy(),而不是memmove()),但Python和NumPy的最终用户可能不会想到这一点。我没有找到任何文件表明这行不通。

    问题是:这里的NumPy中是否存在错误(可能没有),或者是否有一些NumPy文档解释了在这种情况下的规则,或者文档中缺少这些规则?

    其次,我想找出一个在空间和时间上都是准最优的安全、有效的解决方案。也就是说,它不应该分配超过常量的内存,也不应该是一个愚蠢的纯Python“for”循环这些都是人们可能希望通过就地修改实现的目标,而这种修改显然行不通。

    我正在使用NumPy 1.8.0。

    3 回复  |  直到 10 年前
        1
  •  1
  •   hpaulj    10 年前

    我再次在这里发帖来更正我的答案。 也许可以尝试:

    bc-=np.roll( bc , 1 )
    
    #array([-9,  1,  1,  1,  1,  1,  1,  1,  1,  1])
    #this arrays length is 10
    
    #and then for an array with length 9
    bc=bc[ 1 : ]  
    
    #array([1,  1,  1,  1,  1,  1,  1,  1,  1])
    

    抱歉小姐之前理解了这个问题,

    结果的原因:

    'array([0, 1, 1, 2, 2, 3, 3, 4, 4, 5])'
    

    这个动作实际上被语法化为

    let (say...) a=array([0,1,2,3,4,5,6,7,8,9])
    updated a <- will be formed as [0, 1-0=1,2-1=1,3-1=2,4-2=2,5-2=3,6-3=3,7-3=4,8-4=4,9-4=5] 
    

    我认为你真正想要的是

    tnx EdChum公司

        2
  •  0
  •   fredtantini    10 年前

    我不认为这是一个错误:
    正在执行 bc[1:] -= bc[:-1] 您在执行操作时正在修改列表。

    过程如下

    for i in range(1,len(bc)):
        bc[i] = bc[i] - bc[i-1]
    

    所以下一步 bc[i-1] 已修改:

    "i"      1
    bc[1:]:  1,2,3,4,5,…
    bc[:-1]: 0,1,2,3,4,5,… 
    bc[1]= 1 - 0 = 1
    new bc: 0,1,2,3,4,5,…
    
    "i"        2
    bc[1:]:  1,2,3,4,5,…
    bc[:-1]: 0,1,2,3,4,5,… 
    bc[2]= 2 - 1 = 1
    new bc: 0,1,1,3,4,5,…
    
    
    "i"          3
    bc[1:]:  1,1,3,4,5,…
    bc[:-1]: 0,1,1,3,4,5,… 
    bc[1]= 3 - 1 = 2
    new bc: 0,1,1,2,4,5,…
    
    
    "i"            4
    bc[1:]:  1,1,2,4,5,…
    bc[:-1]: 0,1,1,2,4,5,… 
    bc[1]= 4 - 2 = 2
    new bc: 0,1,1,2,2,5,…
    

    等等。

    剩下的问题,我无法回答。

        3
  •  0
  •   Community CDub    8 年前

    在发布这个问题后,我确实找到了一些讨论。搜索的重要术语是“切片”。在这里: http://numpy-discussion.10968.n7.nabble.com/Strange-behavior-in-setting-masked-array-values-in-Numpy-1-1-0-td11999.html

    页面下方有关于尝试检测和警告此类事件的讨论,但这听起来像是一个失败的原因。所以我开始寻找另一种就地方法来做我想做的事。给你!

    bc[-1:0:-1] -= bc[-2::-1]
    

    贷方至 @fredtantini 用于显式编写NumPy有效执行的纯Python“for”循环。这让我开始思考如何在纯Python中修复它(向后迭代!),这导致了上述解决方案。