Numpy: views vs copy by slicing

前端 未结 3 1115
花落未央
花落未央 2020-12-05 14:44

When I am doing the slicing, an unexpected thing happened that seems the first to be view but the second is copy.

First

First slice of row, then slice of

相关标签:
3条回答
  • 2020-12-05 15:44

    The accepted answer by John Zwinck is actually false (I just figured this out the hard way!). The problem in the question is a combination of doing "lvalue indexing" with numpy's fancy indexing. The following doc explains exactly this case

    https://scipy-cookbook.readthedocs.io/items/ViewsVsCopies.html

    in the section "But fancy indexing does seem to return views sometimes, doesn't it?"

    0 讨论(0)
  • 2020-12-05 15:45

    All that matters is whether you slice by rows or by columns. Slicing by rows can return a view because it is a contiguous segment of the original array. Slicing by column must return a copy because it is not a contiguous segment. For example:

    A1 A2 A3
    B1 B2 B3
    C1 C2 C3
    

    By default, it is stored in memory this way:

    A1 A2 A3 B1 B2 B3 C1 C2 C3
    

    So if you want to choose every second row, it is:

    [A1 A2 A3] B1 B2 B3 [C1 C2 C3]
    

    That can be described as {start: 0, size: 3, stride: 6}.

    But if you want to choose every second column:

    [A1] A2 [A3 B1] B2 [B3 C1] C2 [C3]
    

    And there is no way to describe that using a single start, size, and stride. So there is no way to construct such a view.

    If you want to be able to view every second column instead of every second row, you can construct your array in column-major aka Fortran order instead:

    np.array(a, order='F')
    

    Then it will be stored as such:

    A1 B1 C1 A2 B2 C2 A3 B3 C3
    
    0 讨论(0)
  • 2020-12-05 15:45

    This is my understanding, for your reference

    a[0:3:2, :]                     # basic indexing, a view
    ... = a[0:3:2, :][:, [0, 2]]    # getitme version, a copy,
                                    # because you use advanced
                                    # indexing [:,[0,2]]
    a[0:3:2, :][:, [0, 2]] = ...    # howver setitem version is
                                    # like a view, setitem version
                                    # is different from getitem version,
                                    # this is not c++
    a[:, [0, 2]]                    # getitem version, a copy,
                                    # because you use advanced indexing
    a[:, [0, 2]][0:3:2, :] = 0      # the copy is modied,
                                    # but a keeps unchanged.
    

    If I have any misunderstanding, please point it out.

    0 讨论(0)
提交回复
热议问题