我使用外部库函数返回一个numpy结构化数组。
cities_array
>>> array([ (1, [-122.46818353792992, 48.74387985436505], u'05280', u'Bellingham', u'53', u'Washington', u'5305280', u'city', u'N', -99, 52179),
(2, [-109.67985528815007, 48.54381826401885], u'35050', u'Havre', u'30', u'Montana', u'3035050', u'city', u'N', 2494, 10201),
(3, [-122.63068540357023, 48.49221584868184], u'01990', u'Anacortes', u'53', u'Washington', u'5301990', u'city', u'N', -99, 11451),
...,
(3147, [-156.45657614262274, 20.870633142444376], u'22700', u'Kahului', u'15', u'Hawaii', u'1522700', u'census designated place', u'N', 7, 16889),
(3148, [-156.45038252004554, 20.76059218396], u'36500', u'Kihei', u'15', u'Hawaii', u'1536500', u'census designated place', u'N', -99, 11107),
(3149, [-155.08472452266503, 19.693112205773275], u'14650', u'Hilo', u'15', u'Hawaii', u'1514650', u'census designated place', u'N', 38, 37808)],
dtype=[('ID', '<i4'), ('Shape', '<f8', (2,)), ('CITY_FIPS', '<U5'), ('CITY_NAME', '<U40'), ('STATE_FIPS', '<U2'), ('STATE_NAME', '<U25'), ('STATE_CITY', '<U7'), ('TYPE', '<U25'), ('CAPITAL', '<U1'), ('ELEVATION', '<i4'), ('POP1990', '<i4')])
cities_array
的类型为<type 'numpy.ndarray'>
。
我可以访问数组的各个列:
cities_array[['ID','CITY_NAME']]
>>> array([(1, u'Bellingham'), (2, u'Havre'), (3, u'Anacortes'), ...,
(3147, u'Kahului'), (3148, u'Kihei'), (3149, u'Hilo')],
dtype=[('ID', '<i4'), ('CITY_NAME', '<U40')])
现在我要删除第一列ID
。 help和SO questions表示它应为numpy.delete
。
运行时:numpy.delete(cities_array,cities_array['ID'],1)
我收到错误消息:
...in delete
N = arr.shape[axis]
IndexError: tuple index out of range
我做错了什么?我应该对cities_array进行后期处理才能使用数组吗?
我使用的是Python 2.7.10和numpy 1.11.0
答案 0 :(得分:2)
我认为这应该有效:
def delete_colum(array, *args):
filtered = [x for x in array.dtype.names if x not in args]
return array[filtered]
数组示例:
a
Out[9]:
array([(1, [-122.46818353792992, 48.74387985436505])],
dtype=[('ID', '<i4'), ('Shape', '<f8', (2,))])
delete_colum(a,'ID')
Out[11]:
array([([-122.46818353792992, 48.74387985436505],)],
dtype=[('Shape', '<f8', (2,))])
答案 1 :(得分:1)
你发表评论:
但这样的基本操作失败并不奇怪吗?只是一个简单的数组
x = numpy.zeros(3, dtype={'names':['col1', 'col2'], 'formats':['i4','f4']})
无法删除numpy.delete(x,0,1)
的列。什么是这个问题的溃败原因,任何想法?
np.delete
不是基本操作。看看它的代码。它的长度为5个屏幕(在Ipython上)。其中很多都处理了指定删除元素的不同方式。
有关 np.delete(x,0,axis = 1)
它使用特殊情况
# optimization for a single value
...
newshape[axis] -= 1
new = empty(newshape, arr.dtype, arrorder)
slobj[axis] = slice(None, obj)
new[slobj] = arr[slobj]
slobj[axis] = slice(obj, None)
slobj2 = [slice(None)]*ndim
slobj2[axis] = slice(obj+1, None)
new[slobj] = arr[slobj2]
对于2d数组,轴= 1,它确实:
new = np.zeros((x.shape[0], x.shape[1]-1), dtype=x.dtype)
new[:, :obj] = x[:, :obj]
new[:, obj:] = x[:, obj+1:]
换句话说,它分配一个新的数组,其中列数少于1,然后将两个切片从原始数据复制到它。
有多个删除列和布尔obj
,它需要其他路由。
请注意,该操作的基础是能够索引2个维度。
但是你不能用你的x
索引。 x[0,1]
出现too many indices
错误。您必须使用x[0]['col1']
。索引dtype
的字段与索引二维数组的列有根本的不同。
recfunctions
以常规dtype
函数的方式操纵numpy
字段。根据之前的研究,我猜测drop_field
做了类似的事情:
In [57]: x # your x with some values
Out[57]:
array([(1, 3.0), (2, 2.0), (3, 1.0)],
dtype=[('col1', '<i4'), ('col2', '<f4')])
目标数组,具有不同的dtype
(缺少一个字段)
In [58]: y=np.zeros(x.shape, dtype=x.dtype.descr[1:])
按字段复制值:
In [60]: for name in y.dtype.names:
...: y[name]=x[name]
In [61]: y
Out[61]:
array([(3.0,), (2.0,), (1.0,)],
dtype=[('col2', '<f4')])
常规n-d索引是围绕shape
和strides
属性构建的。通过这些(以及元素字节大小),它可以快速识别所需元素的data
缓冲区中的位置。
使用复合dtype
,形状和步幅的工作方式相同,但nbytes
不同。在x
案例中,i4
和f4
字段各为24 - 12。因此,从一个24位记录到下一个记录的常规索引步骤。所以要选择&#39; col2&#39;字段,它进一步选择每个记录中的第二组4个字节。
在可能的情况下,我认为它将字段选择转换为常规索引。 __array_interface__
是一个很好的数组基本属性字典。
In [70]: x.__array_interface__
Out[70]:
{'data': (68826112, False),
'descr': [('col1', '<i4'), ('col2', '<f4')],
'shape': (3,),
'strides': None,
'typestr': '|V8',
'version': 3}
In [71]: x['col2'].__array_interface__
Out[71]:
{'data': (68826116, False),
'descr': [('', '<f4')],
'shape': (3,),
'strides': (8,),
'typestr': '<f4',
'version': 3}
第二个数组指向相同的数据缓冲区,但进一步指向4个字节(第一个col2
值)。实际上它是一种观点。
(np.transpose
是另一个不在dtype
边界内运作的函数。)
===================
这里是drop_fields
的代码(摘要):
In [74]: from numpy.lib import recfunctions # separate import statement
In [75]: recfunctions.drop_fields??
def drop_fields(base, drop_names, usemask=True, asrecarray=False):
.... # define `drop_descr function
newdtype = _drop_descr(base.dtype, drop_names)
output = np.empty(base.shape, dtype=newdtype)
output = recursive_fill_fields(base, output)
return output
recursive_fill_fields
按名称字段副本执行名称,并且能够处理定义字段中字段的dtypes(递归部分)。
In [81]: recfunctions.drop_fields(x, 'col1')
Out[81]:
array([(3.0,), (2.0,), (1.0,)],
dtype=[('col2', '<f4')])
In [82]: x[['col2']] # multifield selection that David suggests
Out[82]:
array([(3.0,), (2.0,), (1.0,)],
dtype=[('col2', '<f4')])
In [83]: x['col2'] # single field view
Out[83]: array([ 3., 2., 1.], dtype=float32)
drop_field
产生与@David建议的多字段索引类似的结果。但是,多字段索引编写得很糟糕,正如您将尝试进行某种分配一样。