我有一个NumPy
数组,其中包含40多列。我的目标只是创建另一个数组,其中包含这些列的子集并附加数据。
我的代码是:
RecDtypes = []
RecColIds = ['REC*','GLOBAL*']
for name in Reconciliation.dtype.names:
for Id in RecColIds:
if fnmatch.fnmatch(name,Id):
RecDtypes.append(name)
#Change column names
if RecDtypes:
Rec = Reconciliation[RecDtypes]
newnames=[]
for oldname in Rec.dtype.names:
for Id in RecColIds:
if fnmatch.fnmatch(oldname,Id):
newnames.append(oldname[len(Id):])
Rec.dtype.names=newnames
此处Rec = new array
和Reconciliation = old array
。第一个循环从第一个数组中提取出我想要的列。第二个循环重命名列名。
这是一种更简单/有效/简洁的方法吗?
答案 0 :(得分:1)
根据您对问题的描述,我不知道这将是多么紧张的计算(40列= 40个字符串来测试和移动)。你可以通过组合你的两个循环消除一些混乱,因为它们有效地循环在相同的列表上。这也可能会带来轻微的性能优势,但从我的第一句话来看,这可能是微不足道的。
RecDtypes = []
newnames = []
RecColIds = ['REC*','GLOBAL*']
for name in Reconciliation.dtype.names:
for Id in RecColIds:
if fnmatch.fnmatch(name,Id):
RecDtypes.append(name)
newnames.append(name[len(Id):])
#Change column names
if RecDtypes:
Rec = Reconciliation[RecDtypes]
Rec.dtype.names=newnames
答案 1 :(得分:1)
这看起来像是复制和重命名任务:
In [95]: dt = np.dtype('i,i,i,i')
In [96]: arr = np.zeros((2,), dtype=dt)
In [97]: arr[0]=np.arange(4)
In [98]: arr[1]=np.arange(4,8)
In [99]: arr
Out[99]:
array([(0, 1, 2, 3), (4, 5, 6, 7)],
dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4'), ('f3', '<i4')])
获取符合某种模式的名称列表:
In [100]: alist = [name for name in dt.names if name[1] in ['1','3']]
In [101]: alist
Out[101]: ['f1', 'f3']
按字段名称进行直接复制:
In [102]: arr1 = arr[alist]
In [103]: arr1
Out[103]:
array([(1, 3), (5, 7)],
dtype=[('f1', '<i4'), ('f3', '<i4')])
直接改变字段名称:
In [104]: arr1.dtype.names = ['one','three']
In [105]: arr1
Out[105]:
array([(1, 3), (5, 7)],
dtype=[('one', '<i4'), ('three', '<i4')])
如果您打算修改值,则需要使用arr1 = arr[alist].copy()
:
In [107]: arr1['one'] += 1
/usr/local/bin/ipython3:1: FutureWarning: Numpy has detected that you (may be) writing to an array returned
by numpy.diagonal or by selecting multiple fields in a structured
array. This code will likely break in a future numpy release --
see numpy.diagonal or arrays.indexing reference docs for details.
The quick fix is to make an explicit copy (e.g., do
arr.diagonal().copy() or arr[['f0','f1']].copy()).
#!/usr/bin/python3
子模块numpy.lib.recfunctions
具有复制和修改结构化数组及其名称的功能。通常,这些函数的工作原理是创建一个具有所需形状和dtype的空目标数组,然后按字段名称将值从old复制到new。这似乎就是你在做什么。
通常,结构化数组将包含许多行,并且字段相对较少。因此,字段的迭代复制并不昂贵。
您可以使用名称列表
一次访问多个字段arr[['f0','f1']]
编辑 - 您的Reconciliation[RecDtypes]
正是这样做的。一次取出几个字段。
但是如果你做了什么而不是阅读这些值,你可能会收到警告,建议你添加copy
。最近的numpy
发行说明有关于按位置从副本更改为按位置复制的内容。
按字段名称说明副本:
In [128]: alist
Out[128]: ['f1', 'f3']
In [129]: arr
Out[129]:
array([(0, 1, 2, 3), (4, 5, 6, 7)],
dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4'), ('f3', '<i4')])
In [130]: dt.descr
Out[130]: [('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4'), ('f3', '<i4')]
In [131]: dt1 = [item for item in dt.descr if item[0] in alist]
In [132]: dt1
Out[132]: [('f1', '<i4'), ('f3', '<i4')]
In [133]: res = np.zeros(arr.shape, dtype=dt1)
In [134]: for name in alist:
...: res[name] = arr[name]
In [135]: res
Out[135]:
array([(1, 3), (5, 7)],
dtype=[('f1', '<i4'), ('f3', '<i4')])
arr[alist].copy()
更简单,可能更快。