genfromtxt() 中的 NumPy dtype 问题,将字符串读取为字节串

Posted

技术标签:

【中文标题】genfromtxt() 中的 NumPy dtype 问题,将字符串读取为字节串【英文标题】:NumPy dtype issues in genfromtxt(), reads string in as bytestring 【发布时间】:2014-03-24 08:08:30 【问题描述】:

我想将一个标准的 ascii csv 文件读入 numpy,它由浮点数和字符串组成。

例如,

ZINC00043096,C.3,C1,-0.1540,methyl
ZINC00043096,C.3,C2,0.0638,methylene
ZINC00043096,C.3,C4,0.0669,methylene
ZINC00090377,C.3,C7,0.2070,methylene
...

无论我尝试什么,结果数组都会是这样的

例如,

all_data = np.genfromtxt(csv_file, dtype=None, delimiter=',')


[(b'ZINC00043096', b'C.3', b'C1', -0.154, b'methyl')
 (b'ZINC00043096', b'C.3', b'C2', 0.0638, b'methylene')
 (b'ZINC00043096', b'C.3', b'C4', 0.0669, b'methylene')

但是,我想为字节字符串转换保存一个步骤,并且想知道如何将字符串列作为常规字符串直接读取。

我从 numpy.genfromtxt() 文档中尝试了几件事,例如,dtype='S,S,S,f,S'dtype='a25,a25,a25,f,a25',但这里没有任何帮助。

我很害怕,但我想我只是不明白 dtype 转换是如何工作的......如果你能在这里给我一些提示会很好!

谢谢

【问题讨论】:

你为什么这么讨厌np.bytes_ 旁白:根据我的经验,当人们想要将文本和数字都放入一个 numpy 数组时,他们通常最好使用 pandas DataFrame @zhangxaochen - 如果我没记错的话(目前无法在 python3 上测试),将列作为字节将不允许您使用 numpy 的矢量化字符串操作。不过我可能记错了。 【参考方案1】:

在 python 3.6 中,

all_data = np.genfromtxt('csv_file.csv', delimiter=',', dtype='unicode')

工作得很好。

【讨论】:

工作就像一个魅力!【参考方案2】:

在 Python2.7 中

array([('ZINC00043096', 'C.3', 'C1', -0.154, 'methyl'),
       ('ZINC00043096', 'C.3', 'C2', 0.0638, 'methylene'),
       ('ZINC00043096', 'C.3', 'C4', 0.0669, 'methylene'),
       ('ZINC00090377', 'C.3', 'C7', 0.207, 'methylene')], 
      dtype=[('f0', 'S12'), ('f1', 'S3'), ('f2', 'S2'), ('f3', '<f8'), ('f4', 'S9')])

在 Python3 中

array([(b'ZINC00043096', b'C.3', b'C1', -0.154, b'methyl'),
       (b'ZINC00043096', b'C.3', b'C2', 0.0638, b'methylene'),
       (b'ZINC00043096', b'C.3', b'C4', 0.0669, b'methylene'),
       (b'ZINC00090377', b'C.3', b'C7', 0.207, b'methylene')], 
      dtype=[('f0', 'S12'), ('f1', 'S3'), ('f2', 'S2'), ('f3', '<f8'), ('f4', 'S9')])

Python3 中的“常规”字符串是 unicode。但是您的文本文件有字节字符串。 all_data 在两种情况下都是相同的(136 字节),但 Python3 显示字节字符串的方式是 b'C.3',而不仅仅是 'C.3'。

您打算对这些字符串进行哪些操作? 'ZIN' in all_data['f0'][1] 适用于 2.7 版本,但在 3 中您必须使用 b'ZIN' in all_data['f0'][1]

Variable/unknown length string/unicode dtype in numpy 提醒我,您可以在 dtype 中指定 unicode 字符串类型。但是,如果您事先不知道字符串的长度,这会变得更加复杂。

alttype = np.dtype([('f0', 'U12'), ('f1', 'U3'), ('f2', 'U2'), ('f3', '<f8'), ('f4', 'U9')])
all_data_u = np.genfromtxt(csv_file, dtype=alttype, delimiter=',')

生产

array([('ZINC00043096', 'C.3', 'C1', -0.154, 'methyl'),
       ('ZINC00043096', 'C.3', 'C2', 0.0638, 'methylene'),
       ('ZINC00043096', 'C.3', 'C4', 0.0669, 'methylene'),
       ('ZINC00090377', 'C.3', 'C7', 0.207, 'methylene')], 
      dtype=[('f0', '<U12'), ('f1', '<U3'), ('f2', '<U2'), ('f3', '<f8'), ('f4', '<U9')])

在 Python2.7 中 all_data_u 显示为

(u'ZINC00043096', u'C.3', u'C1', -0.154, u'methyl')

all_data_u 是 448 个字节,因为numpy 为每个 unicode 字符分配 4 个字节。每个U4 项的长度为 16 个字节。


v 1.14 中的更改:https://docs.scipy.org/doc/numpy/release.html#encoding-argument-for-text-io-functions

【讨论】:

这需要你先验地知道dtype,而python2.7的解决方案允许你指定dtype=None。是否有任何类似的行为会在 python3 中转换为 unicode?​​span> dtype=None 在 py2 和 3 中创建字节串。similar behavior 可以以两种方式解释 - 作为字节串,或作为默认字符串。 @kadrlica 1.14 版通过encoding 参数为我们提供了更大的灵活性。查看最近的***.com/questions/48723311/…【参考方案3】:
np.genfromtxt(csv_file, dtype='|S12', delimiter=',')

或者您可以使用usecols 参数选择您知道是字符串的列:

np.genfromtxt(csv_file, dtype=None, delimiter=',',usecols=(0,1,2,4))

【讨论】:

以上是关于genfromtxt() 中的 NumPy dtype 问题,将字符串读取为字节串的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 genfromtxt() 从 NumPy 中的文本文件中读取不同长度的列?

Numpy使用genfromtxt解析日期

numpy genfromtxt IndexError 使用评论时

使用 numpy.genfromtxt 读取包含逗号的字符串的 csv 文件

Numpy函数学习--genfromtxt函数

NumPy之:使用genfromtxt导入数据