Numpy genfromtxt - 在读取文件时是否可以为缺少的字段设置默认类型?

时间:2015-11-18 13:53:05

标签: python numpy

我使用numpy genfromtxt来读取CSV数据文件,然后将其堆叠成单个结构化的numpy数组。但是,我遇到了一些问题,因为在某些文件中,某些字段中缺少所有数据。因此,当我尝试堆叠数据时,我得到一个“TypeError:Incompatible type”,该字段包含所有缺失的数据。

有没有办法通过在genfromtxt中设置默认的missing_values dtype,或者在堆叠数组时以某种方式处理类型不匹配来处理这个问题?

注意,我不知道字段数据类型将提前是什么。

import numpy as np
import numpy.lib.recfunctions as RF

#=====================================================
#------------ file test0.csv ---------- 
# fld1, fld2, fld3, fld4, fld5
# aaa, 1, , 3.0, 4
# bbb, 2, , 4.1, 3
# ccc, 3, , 5.2, 2
# ddd, 4, , 6.3, 1
# 
#------------ file test1.csv ---------- 
# fld1, fld2, fld3, fld4, fld5
# aaa, 1, 2.0, 3.0, 4
# bbb, 2, 2.1, 4.1, 3
# ccc, 3, 2.2, 5.2, 2
# ddd, 4, 2.3, 6.3, 1
#    
#====================================================================
fn0 = r'C:\temp\test0.csv'
fn1 = r'C:\temp\test1.csv'

a0 = np.genfromtxt(fn0, dtype=None, delimiter=',', names=True)
a1 = np.genfromtxt(fn1, dtype=None, delimiter=',', names=True)

da = RF.stack_arrays((a0,a1))

1 个答案:

答案 0 :(得分:0)

您的样本a2.dtype

dtype=[('fld1', 'S3'), ('fld2', '<i4'), 
       ('fld3', '<f8'), ('fld4', '<f8'), ('fld5', '<i4')

但适用于a1 ('fld3', '?'),因为没有数据可以从中推断出类型。

如果我定义了一个dtype列表

dt=['S3',int,float,float,int]
a2 = np.genfromtxt(txt2, dtype=dt, delimiter=',', names=True)
a1 = np.genfromtxt(txt1, dtype=dt, delimiter=',', names=True)

然后数组有一个共同的dtype,我可以连接(不需要RF版本):

In [25]: np.concatenate([a1,a2],axis=0)
Out[25]: 
array([(b'aaa', 1, nan, 3.0, 4), (b'bbb', 2, nan, 4.1, 3),
       (b'ccc', 3, nan, 5.2, 2), (b'ddd', 4, nan, 6.3, 1),
       (b'aaa', 1, 2.0, 3.0, 4), (b'bbb', 2, 2.1, 4.1, 3),
       (b'ccc', 3, 2.2, 5.2, 2), (b'ddd', 4, 2.3, 6.3, 1)], 
      dtype=[('fld1', 'S3'), ('fld2', '<i4'), ('fld3', '<f8'), ('fld4', '<f8'), ('fld5', '<i4')])

我没有看到像dt这样明确的列表。我可以看到参数中没有任何内容,我可以说,例如,在使用dtype=None时,未知列应为float

创建后,更改所选字段的dtype以使其兼容需要花费大量的精力。改名很容易。但是更改字段dtype很可能需要创建一个新的空数组并复制字段。

查看a1.itemsizea2.itemsize。它们分别是20和27。

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

这是加载后更改dtype的示例。 a1na2n是使用dtype=None创建的数组:

来自a1的形状为空的数组,但来自a2的dtype:

In [31]: a1nn = np.zeros(a1n.shape, dtype=a2n.dtype)
In [32]: for n in a1nn.dtype.names:  
   ....:     a1nn[n]=a1n[n]     # copy fields by name
   ....:     
In [33]: a1nn
Out[33]: 
array([(b'aaa', 1, 0.0, 3.0, 4), (b'bbb', 2, 0.0, 4.1, 3),
       (b'ccc', 3, 0.0, 5.2, 2), (b'ddd', 4, 0.0, 6.3, 1)], 
      dtype=[('fld1', 'S3'), ('fld2', '<i4'), ('fld3', '<f8'), ('fld4', '<f8'), ('fld5', '<i4')])
In [34]: np.concatenate([a1nn,a2n])
Out[34]: 
array([(b'aaa', 1, 0.0, 3.0, 4), (b'bbb', 2, 0.0, 4.1, 3),
       (b'ccc', 3, 0.0, 5.2, 2), (b'ddd', 4, 0.0, 6.3, 1),
       (b'aaa', 1, 2.0, 3.0, 4), (b'bbb', 2, 2.1, 4.1, 3),
       (b'ccc', 3, 2.2, 5.2, 2), (b'ddd', 4, 2.3, 6.3, 1)], 
      dtype=[('fld1', 'S3'), ('fld2', '<i4'), ('fld3', '<f8'), ('fld4', '<f8'), ('fld5', '<i4')])

genfromtxt使用np.nan填充了缺少的字段,但此路由使用了0

RF有一个逐字段复制数组的函数,但是当dtype嵌套时会递归复制。