就地修改NumPy recarray的高级索引子集

3 投票
2 回答
1196 浏览
提问于 2025-04-16 06:39

我有一个叫做recarray的数组,里面有几个列,我用它来选择一部分数据。大概是这样的:

>>> x
   array([ ('label1',True,3),
          ('label2',True,2),
          ('label1',False,4)],
         dtype=[('status', '|S16'), ('select', '|b1'), ('somedata', '<i4')])

我从这个数组中选择数据的方法有点像之前在StackOverflow上提到的一个问题。

condit=(x['status']=='label1')&(x['select']==True)
x_subids=numpy.where(condit)[0]
x_sub=x[x_subids]

然后我会对选出来的这部分数据进行一些处理,并更新原来的数据。

x[x_subids]=x_sub

我知道因为使用了高级索引,所以x_sub是一个副本,而不是原来的视图。我在想有没有什么简单的方法,可以避免创建这个数组的副本,直接在原数组上操作,同时又能满足我需要选择数据的条件。

2 个回答

2

你可以使用一个“掩码数组”:

masked = numpy.ma.array(x, 
                        mask=(x['status']!='label1')|(x['select']!=True),
                        copy=False)

注意,这里的掩码是你的 condit 的反转,因为掩码为 True 的地方会被隐藏。现在你可以对这个掩码数组使用任何 numpy 的通用函数,只有那些没有被隐藏的值会受到影响。

3

你提到的那些修改,可以通过numpy.place()函数来实现:

>>> import numpy
>>> x = numpy.array([("label1",True,3), ("label2",False,2), ("label1",True,4)],
...     dtype=[("status", "|S16"), ("select", "|b1"), ("somedata", ">> mask = x["select"]
>>> numpy.place(x["somedata"], mask, (5, 6))
>>> print x
[('label1', True, 5) ('label2', False, 2) ('label1', True, 6)]
>>> numpy.place(x["status"], mask, "label3")
>>> print x
[('label3', True, 5) ('label2', False, 2) ('label3', True, 6)]

注意以下几点:

  1. 为了举个合适的例子,我稍微改了一下数值和条件。

  2. 这次,maskTrue的值又被选出来了,而不是像我之前的回答那样被屏蔽掉。

  3. 在你的条件condit中,==True这一部分是多余的,可以去掉哦 :)

撰写回答