我通过
从csv创建了一个numpy数组dtest = np.genfromtxt('data/test.csv', delimiter=",", names = True)
该数据有200列,名称为' name',' id',依此类推。 我试图删除' id'柱。
我可以使用列名吗?
答案 0 :(得分:2)
拟议副本中的答案How do you remove a column from a structured numpy array? 展示如何引用结构化数组的字段子集。这可能是你想要的,但它有一个潜在的问题,我将稍微说明一下。
从一个小样本csv'文件'开始:
In [32]: txt=b"""a,id,b,c,d,e
...: a1, 3, 0,0,0,0.1
...: b2, 4, 1,2,3,4.4
...: """
In [33]: data=np.genfromtxt(txt.splitlines(), delimiter=',',names=True, dtype=None)
In [34]: data
Out[34]:
array([(b'a1', 3, 0, 0, 0, 0.1),
(b'b2', 4, 1, 2, 3, 4.4)],
dtype=[('a', 'S2'), ('id', '<i4'), ('b', '<i4'), ('c', '<i4'), ('d', '<i4'), ('e', '<f8')])
我可以通过字段名称列表获得字段子集的“视图”。 'duplicate'显示了如何从data.dtype.names
构建这样的列表。在这里,我只需输入,省略'id'名称。
In [35]: subd=data[['a','b','c','d']]
In [36]: subd
Out[36]:
array([(b'a1', 0, 0, 0), (b'b2', 1, 2, 3)],
dtype=[('a', 'S2'), ('b', '<i4'), ('c', '<i4'), ('d', '<i4')])
问题在于这不是常规的“观察”。它适合阅读,但任何写入子集的尝试都会引发警告。
In [37]: subd[0]['b'] = 3
/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
制作子集副本是可以的。但对subd
的更改不会影响data
。
In [38]: subd=data[['a','b','c','d']].copy()
In [39]: subd[0]['b'] = 3
In [40]: subd
Out[40]:
array([(b'a1', 3, 0, 0), (b'b2', 1, 2, 3)],
dtype=[('a', 'S2'), ('b', '<i4'), ('c', '<i4'), ('d', '<i4')])
从索引列表中删除ith
字段名称的简单方法:
In [60]: subnames = list(data.dtype.names) # list so its mutable
In [61]: subnames
Out[61]: ['a', 'id', 'b', 'c', 'd', 'e']
In [62]: del subnames[1]
由于您正在使用csv
阅读此数组,因此可以使用usecols
加载“id”列以外的所有内容
由于您拥有大量列,因此很容易做出类似的事情:
In [42]: col=list(range(6)); del col[1]
In [43]: col
Out[43]: [0, 2, 3, 4, 5]
In [44]: np.genfromtxt(txt.splitlines(), delimiter=',',names=True, dtype=None,usecols=col)
Out[44]:
array([(b'a1', 0, 0, 0, 0.1), (b'b2', 1, 2, 3, 4.4)],
dtype=[('a', 'S2'), ('b', '<i4'), ('c', '<i4'), ('d', '<i4'), ('e', '<f8')])
有一个函数库可以帮助操作结构化数组
In [45]: import numpy.lib.recfunctions as rf
In [47]: rf.drop_fields(data, ['id'])
Out[47]:
array([(b'a1', 0, 0, 0, 0.1), (b'b2', 1, 2, 3, 4.4)],
dtype=[('a', 'S2'), ('b', '<i4'), ('c', '<i4'), ('d', '<i4'), ('e', '<f8')])
此组中的大多数功能都是通过构建一个目标为dtype
的“空白”数组,然后按字段将值从源复制到目标。
以下是recfunctions
中使用的字段复制方法:
In [65]: data.dtype.descr # dtype description as list of tuples
Out[65]:
[('a', '|S2'),
('id', '<i4'),
('b', '<i4'),
('c', '<i4'),
('d', '<i4'),
('e', '<f8')]
In [66]: desc=data.dtype.descr
In [67]: del desc[1] # remove one field
In [68]: res = np.zeros(data.shape, dtype=desc) # target
In [69]: res
Out[69]:
array([(b'', 0, 0, 0, 0.), (b'', 0, 0, 0, 0.)],
dtype=[('a', 'S2'), ('b', '<i4'), ('c', '<i4'), ('d', '<i4'), ('e', '<f8')])
In [70]: for name in res.dtype.names: # copy by field name
...: res[name] = data[name]
In [71]: res
Out[71]:
array([(b'a1', 0, 0, 0, 0.1), (b'b2', 1, 2, 3, 4.4)],
dtype=[('a', 'S2'), ('b', '<i4'), ('c', '<i4'), ('d', '<i4'), ('e', '<f8')])
由于结构化数组通常有很多记录,而且字段很少,因此按字段名复制相对较快。
链接的SO引用matplotlib.mlab.rec_drop_fields(rec, names)
。这基本上完成了我刚刚概述的内容 - 使用所需字段创建目标,并按名称复制字段。
newdtype = np.dtype([(name, rec.dtype[name]) for name in rec.dtype.names
if name not in names])
答案 1 :(得分:1)
我知道你有一个全面的答案,但这是我刚刚放在一起的另一个答案。
import numpy as np
test1.csv =
a b c id
0 1 2 3
4 5 6 7
8 9 10 11
genfromtxt
导入:d = np.genfromtxt('test1.csv', delimiter="\t", names = True)
d
> array([(0.0, 1.0, 2.0, 3.0), (4.0, 5.0, 6.0, 7.0), (8.0, 9.0, 10.0, 11.0)],
dtype=[('a', '<f8'), ('b', '<f8'), ('c', '<f8'), ('id', '<f8')])
d['a']
> array([ 0., 4., 8.])
要删除名称&#39; id&#39;你可以做到以下几点:
list(d.dtype.names)
> ['a', 'b', 'c', 'id']
id
的列来创建新的numpy数组。使用列表推导功能返回一个新的列表,而不会出现您的&#39; id&#39;字符串:
[b for b in list(d.dtype.names) if b != 'id']
> ['a', 'b', 'c']
d_new = d[[b for b in list(d.dtype.names) if b != 'id']]
> array([(0.0, 1.0, 2.0), (4.0, 5.0, 6.0), (8.0, 9.0, 10.0)],
dtype=[('a', '<f8'), ('b', '<f8'), ('c', '<f8')])
a b c
0 1 2
4 5 6
8 9 10
答案 2 :(得分:0)
这可能是 numpy
中的新功能(适用于 1.20.2),但您可以使用名称列表对命名数组进行切片(尽管名称元组不起作用)。
data = np.genfromtxt('some_file.csv', names=['a', 'b', 'c', 'd', 'e'])
# I don't want colums b or d
sliced = data[['a', 'c', 'd']]
我注意到您需要删除许多名为 id
的列。这些列在由 ['id', 'id_1', 'id_2', ...]
解析时显示为 genfromtxt
等,因此您可以使用一些列表推导来挑选这些列名称并从中切分。
no_ids = data[[n for n in data.dtype.names if 'id' not in n]]