我想更改numpy数组中的值,以下是我尝试过的内容:
import numpy as np
sdd_type = np.dtype(
{'names':['name','age','sex'],'formats':['S32','i','S32']})
sdd = np.array(
[('zhang',35,'M'),('song',34,'F'),('li',45,'M')], dtype=sdd_type
)
print sdd[sdd['name'] == 'song']['age']
#output:array([34])
print sdd[sdd['name'] == 'song']['age'][0]
#output:34
sdd[sdd['name'] == 'song']['age'][0] = 41
print sdd[sdd['name'] == 'song']['age']
#output:array([34]), but expect to be 41
如何将值更改为41?
答案 0 :(得分:2)
@abarnert已经解释了这种行为的原因,但您也可以这样做以索引原始数组而不是副本:
sdd[np.where(sdd['name']=='song')[0][0]]['age']=41
答案 1 :(得分:1)
如Boolean or "mask" index arrays中所述:
与索引数组一样,返回的是数据的副本,而不是切片所获得的视图。
如Assigning values to indexed arrays中所述,当您将直接分配给索引时:
与某些引用(例如数组和掩码索引)不同,总是对数组中的原始数据进行赋值(实际上,没有其他任何内容有意义!)。
但你不是在这里做的。虽然您可以分配到sdd[sdd['name'] == 'song']
并修改原始数组,但分配到sdd[sdd['name'] == 'song']['age']
正在修改副本。
要理解原因,您必须了解索引在Python中的工作原理:spam[eggs][beans][toast] = value
之类的目标调用spam.__getitem__(eggs).__getitem__(beans).__setitem__(toast, value)
; NumPy无法告诉sdd[sdd['name'] == 'song']
部分正在被查找以分配内容而不是访问它。
文档解释了NumPy在简单的情况下如何处理这个问题:
...从包含值为1,1,3,1的原始数据(作为临时数据)中提取新数组,然后将值1添加到临时数据库中,然后将临时数据分配回原始数组
因此,如果您有多个[…]
索引,则必须手动执行相同的操作:
tmp = sdd[sdd['name'] == 'song']
tmp[0]['age'] = 41
sdd[sdd['name'] == 'song'] = tmp
请注意,如果您想立即更新名为song
的所有人,而不是仅更新名为song
的第一个(希望只有?)人,您可以删除[0]
并同样代码可以工作。
但如果您确定只有一个song
并且只想更新他,则可以使用xnx's answer中基于where
的解决方案,这有效地提高了您的倍数索引包括一个掩码索引数组到一个简单的索引中。