我想在 numpy 中扩展结构化数组对象,以便我可以轻松添加新元素。
例如,对于一个简单的结构化数组
>>> import numpy as np
>>> x=np.ndarray((2,),dtype={'names':['A','B'],'formats':['f8','f8']})
>>> x['A']=[1,2]
>>> x['B']=[3,4]
我想轻松地添加一个新元素x['C']=[5,6]
,但随后出现与未定义名称相关的错误'C'
。
只需添加一个新方法即可np.ndarray
:
import numpy as np
class sndarray(np.ndarray):
def column_stack(self,i,x):
formats=['f8']*len(self.dtype.names)
new=sndarray(shape=self.shape,dtype={'names':list(self.dtype.names)+[i],'formats':formats+['f8']})
for key in self.dtype.names:
new[key]=self[key]
new[i]=x
return new
然后,
>>> x=sndarray((2,),dtype={'names':['A','B'],'formats':['f8','f8']})
>>> x['A']=[1,2]
>>> x['B']=[3,4]
>>> x=x.column_stack('C',[4,4])
>>> x
sndarray([(1.0, 3.0, 4.0), (2.0, 4.0, 4.0)],
dtype=[('A', '<f8'), ('B', '<f8'), ('C', '<f8')])
有什么方法可以像字典一样添加新元素?例如
>>> x['C']=[4,4]
>>> x
sndarray([(1.0, 3.0, 4.0), (2.0, 4.0, 4.0)],
dtype=[('A', '<f8'), ('B', '<f8'), ('C', '<f8')])
更新:
通过使用__setitem__
,我离理想的解决方案还有一步之遥,因为我不知道如何:
更改 self 引用的对象
import numpy as np
class sdarray(np.ndarray):
def __setitem__(self, i,x):
if i in self.dtype.names:
super(sdarray, self).__setitem__(i,x)
else:
formats=['f8']*len(self.dtype.names)
new=sdarray(shape=self.shape,dtype={'names':list(self.dtype.names)+[i],'formats':formats+['f8']})
for key in self.dtype.names:
new[key]=self[key]
new[i]=x
self.with_new_column=new
然后
>>> x=sndarray((2,),dtype={'names':['A','B'],'formats':['f8','f8']})
>>> x['A']=[1,2]
>>> x['B']=[3,4]
>>> x['C']=[4,4]
>>> x=x.with_new_column #extra uggly step!
>>> x
sndarray([(1.0, 3.0, 4.0), (2.0, 4.0, 4.0)],
dtype=[('A', '<f8'), ('B', '<f8'), ('C', '<f8')])
更新 2
在选择的答案中正确实施后,我发现问题已经被pandas
DataFrame
对象解决了:
>>> import numpy as np
>>> import pandas as pd
>>> x=np.ndarray((2,),dtype={'names':['A','B'],'formats':['f8','f8']})
>>> x=pd.DataFrame(x)
>>> x['A']=[1,2]
>>> x['B']=[3,4]
>>> x['C']=[4,4]
>>> x
A B C
0 1 3 4
1 2 4 4
>>>