无法将制表符分隔的文件读入 numpy 二维数组

Posted

技术标签:

【中文标题】无法将制表符分隔的文件读入 numpy 二维数组【英文标题】:unable to read a tab delimited file into a numpy 2-D array 【发布时间】:2013-10-13 08:59:48 【问题描述】:

我对 nympy 很陌生,我正在尝试使用以下代码将制表符 (\t) 分隔的文本文件读入 numpy 数组矩阵:

train_data = np.genfromtxt('training.txt', dtype=None, delimiter='\t')

文件内容:

38   Private    215646   HS-grad    9    Divorced    Handlers-cleaners   Not-in-family   White   Male   0   0   40   United-States   <=50K
53   Private    234721   11th   7    Married-civ-spouse  Handlers-cleaners   Husband     Black   Male   0   0   40   United-States   <=50K
30   State-gov  141297   Bachelors  13   Married-civ-spouse  Prof-specialty  Husband     Asian-Pac-Islander  Male   0   0   40   India   >50K

我期望的是一个形状为 (3, 15) 的二维数组矩阵

但使用我上面的代码,我只能得到一个形状为 (3,) 的单行数组

我不知道为什么每行的这 15 个字段没有分别分配一列。

我也尝试使用 numpy 的 loadtxt(),但它无法处理我的数据的类型转换,即即使我给了 dtype=None,它也尝试将字符串转换为默认浮点类型但失败了。

尝试过的代码:

train_data = np.loadtxt('try.txt', dtype=None, delimiter='\t')

Error:
ValueError: could not convert string to float: State-gov

任何指针?

谢谢

【问题讨论】:

您是否尝试过声明“dtype=String”之类的内容? 哦,我可以使用更传统的文件读取来解决这个问题(使用 csv 阅读器) 谢谢@abiessu。 dtype=np.str 工作正常,但我不想将它们全部转换为字符串。因此,我依靠 dtype=None 为我进行自动类型转换,在处理数字时,它使“int”或“float”比字符串具有更高的优先级 【参考方案1】:

实际上这里的问题是np.genfromtxtnp.loadtxt 都返回一个structured array 如果dtype 是结构化的(即,有多种类型)。您的数组报告的形状为(3,),因为从技术上讲,它是“记录”的一维数组。这些“记录”包含您的所有列,但您可以像访问 2d 一样访问所有数据。

您正在正确加载它:

In [82]: d = np.genfromtxt('tmp',dtype=None)

正如您所报告的,它具有一维形状:

In [83]: d.shape
Out[83]: (3,)

但是你所有的数据都在那里:

In [84]: d
Out[84]: 
array([ (38, 'Private', 215646, 'HS-grad', 9, 'Divorced', 'Handlers-cleaners', 'Not-in-family', 'White', 'Male', 0, 0, 40, 'United-States', '<=50K'),
       (53, 'Private', 234721, '11th', 7, 'Married-civ-spouse', 'Handlers-cleaners', 'Husband', 'Black', 'Male', 0, 0, 40, 'United-States', '<=50K'),
       (30, 'State-gov', 141297, 'Bachelors', 13, 'Married-civ-spouse', 'Prof-specialty', 'Husband', 'Asian-Pac-Islander', 'Male', 0, 0, 40, 'India', '>50K')], 
      dtype=[('f0', '<i8'), ('f1', 'S9'), ('f2', '<i8'), ('f3', 'S9'), ('f4', '<i8'), ('f5', 'S18'), ('f6', 'S17'), ('f7', 'S13'), ('f8', 'S18'), ('f9', 'S4'), ('f10', '<i8'), ('f11', '<i8'), ('f12', '<i8'), ('f13', 'S13'), ('f14', 'S5')])

数组的dtype 结构如下:

In [85]: d.dtype
Out[85]: dtype([('f0', '<i8'), ('f1', 'S9'), ('f2', '<i8'), ('f3', 'S9'), ('f4', '<i8'), ('f5', 'S18'), ('f6', 'S17'), ('f7', 'S13'), ('f8', 'S18'), ('f9', 'S4'), ('f10', '<i8'), ('f11', '<i8'), ('f12', '<i8'), ('f13', 'S13'), ('f14', 'S5')])

您仍然可以使用 dtype 中给出的名称访问“列”(称为 字段):

In [86]: d['f0']
Out[86]: array([38, 53, 30])

In [87]: d['f1']
Out[87]: 
array(['Private', 'Private', 'State-gov'], 
      dtype='|S9')

为字段命名更方便:

In [104]: names = "age,military,id,edu,a,marital,job,fam,ethnicity,gender,b,c,d,country,income"

In [105]: d = np.genfromtxt('tmp',dtype=None, names=names)

所以您现在可以访问'age' 字段等:

In [106]: d['age']
Out[106]: array([38, 53, 30])

In [107]: d['income']
Out[107]: 
array(['<=50K', '<=50K', '>50K'], 
      dtype='|S5')

或者35岁以下人群的收入

In [108]: d[d['age'] < 35]['income']
Out[108]: 
array(['>50K'], 
      dtype='|S5')

35 岁以上

In [109]: d[d['age'] > 35]['income']
Out[109]: 
array(['<=50K', '<=50K'], 
      dtype='|S5')

【讨论】:

【参考方案2】:

更新答案

对不起,我看错了你原来的问题:

我期望的是一个形状为 (3, 15) 的二维数组矩阵

但使用我上面的代码,我只能得到一个形状为 (3,) 的单行数组

我想你误解了np.genfromtxt() 会返回什么。在这种情况下,它会尝试推断文本文件中每个“列”的类型并返回structured / "record" array。每行将包含多个字段 (f0...f14),每个字段都可以包含与文本文件中的“列”相对应的不同类型的值。您可以按名称索引特定字段,例如data['f0'].

您只是不能拥有一个(3,15) numpy 异构类型数组。您可以拥有一个(3,15) 同构字符串数组,例如:

>>> string_data = np.genfromtext('test', dtype=str, delimiter='\t')
>>> print string_data.shape
(3, 15)

当然,您可以手动将列转换为您想要的任何类型,如@DrRobotNinja 的回答。但是,您不妨让 numpy 为您创建一个结构化数组,然后按字段对其进行索引并将列分配给新数组。

【讨论】:

【参考方案3】:

我不相信 Numpy 数组在单个数组中处理不同的数据类型。可以做的是将整个数组加载为字符串,然后根据需要将必要的列转换为数字

# Load data as strings
train_data = np.loadtxt('try.txt', dtype=np.str, delimiter='\t')

# Convert numeric strings into integers
first_col = train_data[:,0].astype(np.int)
third_col = train_data[:,2].astype(np.int)

【讨论】:

其实numpy数组可以有结构化dtype,看我的回答。 @askewchan 问题是,numpy 似乎无法处理不同的字段类型来构建二维数组,所以 DrRobotNinja 的回答很有帮助 @ngeek 我鼓励您了解 numpy 如何处理单个数组中的不同字段类型,而不是试图通过将所有数字转换为字符串来超越它。它可能非常有用!在此处查看其他两个答案。

以上是关于无法将制表符分隔的文件读入 numpy 二维数组的主要内容,如果未能解决你的问题,请参考以下文章

将大制表符分隔文件读入R [重复]

在 Spark R 中读取制表符分隔的文本文件

Numpy—— 保存和导入文件

VB.NET:将 CSV 文件读入二维数组

Linux篇--awk的使用

使用带有预定义分隔符的 numpy 保存逐行 txt