【问题标题】:numpy boolean indexing selecting and settingnumpy 布尔索引选择和设置
【发布时间】:2017-12-06 08:42:38
【问题描述】:

我对python不是很熟悉。我最近阅读了《用于数据分析的 Python》一书,我对 numpy 布尔索引和设置有点困惑。 书上说:

通过布尔索引从数组中选择数据总是会创建数据的副本,即使返回的数组没有改变。

使用布尔数组设置值以常识的方式工作。

我已经尝试过如下代码:

第一:

data = np.random.randn(7, 4) 
data[data < 0] = 0 # this could change the `data`

第二:

data = np.random.randn(7, 4) 
copied = data[data < 0]
copied[1] = 1  # this couldn't change the `data`

这里不太明白,谁能解释一下。在我的理解中,copied 应该是指向 data[data

【问题讨论】:

  • 布尔索引创建副本,而不是视图。

标签: python numpy


【解决方案1】:

虽然data[data &lt; 0] = 0 看起来像是设置为0 的视图,但实际情况并非如此。实际上,ndarray 后跟 = 调用处理分段分配的 __setitem__

当 ndarray 位于 = 的另一侧时,不会调用 __setitem__ 并且您分配一个副本(布尔索引总是如此),该副本独立于原始数组。

基本上:

foo[foo != bar] = bar                # calls __setitem__
foo[:2]         = bar                # calls __setitem__
bar             = foo[foo != bar]    # makes a copy
bar             = foo[:2]            # makes a view

【讨论】:

    【解决方案2】:

    根据经验,numpy 会在可能的情况下创建视图并在必要时创建副本。

    什么时候可以查看?当数据可以使用跨步寻址时,例如对于二维数组 A,每个 A[i, j] 位于内存中的地址 base + i*stride[0] + j*stride[1]。如果您只使用切片创建子数组,则总是会出现这种情况,这就是您将获得视图的原因。

    对于逻辑和高级索引,通常不可能找到恰好处理正确元素的基数和跨步。因此,这些操作会返回一个包含复制数据的新数组。

    【讨论】:

      【解决方案3】:

      根据代码的先后顺序:

      1. data = np.random.randn(7, 4) : 这一步创建了一个大小为 7 x 4 的数组
      2. data[data &lt; 0] = 0 :将data中所有
      3. copied = data[data &lt; 0] :这一步生成一个空数组,因为数据中没有元素
      4. copied[1] = 1 :此步骤会引发错误,因为复制的是空数组,因此索引 1 不存在

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-23
        • 2015-05-19
        • 2023-04-03
        • 2021-01-06
        • 2020-03-25
        • 1970-01-01
        相关资源
        最近更新 更多