numpy - 更改/指定掩码数组列的dtypes

时间:2017-01-05 17:57:35

标签: python arrays numpy types masked-array

我有一个包含大量数据的csv文件,我想将其作为屏蔽数组读取。我使用以下方法完成了这项工作:

data=np.recfromcsv(filename,case_sensitive=True,usemask=True)

效果很好。但是,我的问题是数据是字符串,整数或浮点数。我现在要做的是将所有整数转换为浮点数,即将所有“1”转换为“1.0”等,同时保留其他所有内容。

此外,我正在寻找通用的解决方案。因此,只需手动指定所需的类型,因为csv文件(包括列数)会发生变化。

我已经尝试了 astype 但是因为数组也有字符串条目不起作用,或者我错过了什么?

感谢。

1 个答案:

答案 0 :(得分:0)

我还没有使用recfromcsv,但查看其代码后,我看到它使用了np.genfromtxt,然后是屏蔽记录构造。

我建议提供一个小样本csv文本(3行左右),并显示生成的data。我们需要特别看到dtype

genfromtxt开始,暂时跳过蒙面数组的东西也可能很有用。我不认为这是在结构化数组中转换dtypes的关键点。

无论如何,我们需要更具体的东西来探索。

您无法就地更改结构化字段的dtype。您必须使用新的dtype创建一个新数组,并将值从旧的复制到新的。

import numpy.lib.recfunctions as rf

有一些函数可以帮助改变结构化数组。

===========

我怀疑在调用dtypes时拼出genfromtxt比在现有数组中更改dtypes更简单。

您可以尝试使用dtype=None和有限行数进行一次阅读,以获得列数和基数dtype。然后编辑,根据需要用浮点代替整数。现在用新的dtype读取整个内容。如果您需要有关如何编辑dtypes的想法,请查看recfunctions代码。

例如:

In [504]: txt=b"""a, 1, 2, 4\nb, 6, 9, 10\nc, 4, 4, 3"""

In [506]: arr = np.genfromtxt(txt.splitlines(), dtype=None, delimiter=',')
In [507]: arr
Out[507]: 
array([(b'a', 1, 2, 4), (b'b', 6, 9, 10), (b'c', 4, 4, 3)], 
      dtype=[('f0', 'S1'), ('f1', '<i4'), ('f2', '<i4'), ('f3', '<i4')])
In [508]: arr.dtype.descr
Out[508]: [('f0', '|S1'), ('f1', '<i4'), ('f2', '<i4'), ('f3', '<i4')]

原型dtype编辑器:

def foo(tup):
    name, dtype=tup
    dtype = dtype.replace('S','U')
    dtype = dtype.replace('i','f')
    return name, dtype

将此应用于默认dtype:

In [511]: dt = [foo(tup) for tup in arr.dtype.descr]
In [512]: dt
Out[512]: [('f0', '|U1'), ('f1', '<f4'), ('f2', '<f4'), ('f3', '<f4')]

In [513]: arr = np.genfromtxt(txt.splitlines(), dtype=dt, delimiter=',')
In [514]: arr
Out[514]: 
array([('a', 1.0, 2.0, 4.0), ('b', 6.0, 9.0, 10.0), ('c', 4.0, 4.0, 3.0)], 
      dtype=[('f0', '<U1'), ('f1', '<f4'), ('f2', '<f4'), ('f3', '<f4')])

In [522]: arr = np.recfromcsv(txt.splitlines(), dtype=dt, delimiter=',',case_sensitive=True,usemask=True,names=None)
In [523]: arr
Out[523]: 
masked_records(
    f0 : ['a' 'b' 'c']
    f1 : [1.0 6.0 4.0]
    f2 : [2.0 9.0 4.0]
    f3 : [4.0 10.0 3.0]
    fill_value : ('N', 1.0000000200408773e+20, 1.0000000200408773e+20, 1.0000000200408773e+20)
              )

=====================

如果目标dtype匹配,则

astype有效。例如,如果我使用dtype = None读取txt,然后使用派生的dt,则可以使用:

In [530]: arr = np.genfromtxt(txt.splitlines(), delimiter=',',dtype=None)
In [531]: arr
Out[531]: 
array([(b'a', 1, 2, 4), (b'b', 6, 9, 10), (b'c', 4, 4, 3)], 
      dtype=[('f0', 'S1'), ('f1', '<i4'), ('f2', '<i4'), ('f3', '<i4')])
In [532]: arr.astype(dt)
Out[532]: 
array([('a', 1.0, 2.0, 4.0), ('b', 6.0, 9.0, 10.0), ('c', 4.0, 4.0, 3.0)], 
      dtype=[('f0', '<U1'), ('f1', '<f4'), ('f2', '<f4'), ('f3', '<f4')])

arr.astype('U3,int,float,int')同样有4个兼容字段。