大 TSV 文件中主要为整数的字符串列的不一致 pandas read_csv dtype 推断

Posted

技术标签:

【中文标题】大 TSV 文件中主要为整数的字符串列的不一致 pandas read_csv dtype 推断【英文标题】:Inconsistent pandas read_csv dtype inference on mostly-integer string column in huge TSV file 【发布时间】:2013-08-30 13:54:49 【问题描述】:

我有一个制表符分隔的文件,其中有一列应被解释为字符串,但许多条目都是整数。对于小文件,read_csv 在看到一些非整数值后会正确地将列解释为字符串,但对于较大的文件,这不起作用:

import pandas as pd
df = pd.DataFrame('a':['1']*100000 + ['X']*100000 + ['1']*100000, 'b':['b']*300000)
df.to_csv('test', sep='\t', index=False, na_rep='NA')
df2 = pd.read_csv('test', sep='\t')
print df2['a'].unique()
for a in df2['a'][262140:262150]:
    print repr(a)

输出:

['1' 'X' 1]
'1'
'1'
'1'
'1'
1
1
1
1
1
1

有趣的是 262144 是 2 的幂,所以我认为推理和转换是分块进行的,但会跳过一些块。

我相当肯定这是一个错误,但想要一个可能使用引用的解决方法,尽管添加 引用=csv.QUOTE_NONNUMERIC 对于阅读和写作并不能解决问题。理想情况下,我可以通过引用我的字符串数据来解决这个问题,并以某种方式强制 pandas 不对引用的数据进行任何推断。

使用熊猫 0.12.0

【问题讨论】:

docs 让它看起来像这样可以工作:pd.read_csv('test', sep='\t', converters='a':str) @StevenRumbalski 完全可以!您应该将此添加为答案! @AndyHayden:谢谢——完成了。 【参考方案1】:

为避免 Pandas 推断您的数据类型,请为 read_csv 提供一个 converters 参数:

converters : 字典。可选

用于转换某些列中的值的函数字典。键可以是整数或列标签

对于您的文件,这看起来像:

df2 = pd.read_csv('test', sep='\t', converters='a':str)

我对文档的阅读是,您不需要为每一列指定转换器。 Pandas 应该继续推断未指定列的数据类型。

【讨论】:

【参考方案2】:

你在这里欺骗了 read_csv 解析器(公平地说,我不认为它可以总是无论你扔什么都能正确输出)......但是是的,可能是a bug!

正如@Steven 指出的,您可以使用read_csv 的转换器参数:

df2 = pd.read_csv('test', sep='\t', converters='a': str)

一个懒惰的解决方案是在你读完文件后修补它:

In [11]: df2['a'] = df2['a'].astype('str')

# now they are equal
In [12]: pd.util.testing.assert_frame_equal(df, df2)

注意:如果您正在寻找存储数据帧的解决方案,例如在会话之间,pickle 和 HDF5Store 都是出色的解决方案,它们不会受到这些类型的解析错误的影响(并且会更快)。 请参阅:How to store data frame using PANDAS, Python

【讨论】:

这是我的后备方案,但每次读取我试图避免的文件时都会涉及额外的代码行 解决方案可能不是使用 to_csv/read_csv 来存储 DataFrames,to_pickle 或 hdf5_store 是更好的解决方案(并且都不会受到这种解析错误的影响)。 如你所说,长期的解决方案是迁移到 HDF5Store

以上是关于大 TSV 文件中主要为整数的字符串列的不一致 pandas read_csv dtype 推断的主要内容,如果未能解决你的问题,请参考以下文章

如何在python中读取一个大的tsv文件并将其转换为csv

TSV文件将字符串转换为数字

如何检查 SQL Server 2008 表中字符串列中的 id

使用pyspark将两个字符串列值连接到整数数组

AWS Athena数据集的注意事项? TSV

MySQL字符串列与整数比较