熊猫 read_csv dtype 前导零

Posted

技术标签:

【中文标题】熊猫 read_csv dtype 前导零【英文标题】:Pandas read_csv dtype leading zeros 【发布时间】:2013-05-31 12:16:33 【问题描述】:

所以我正在读取来自 NOAA 的站代码 csv 文件,如下所示:

"USAF","WBAN","STATION NAME","CTRY","FIPS","STATE","CALL","LAT","LON","ELEV(.1M)","BEGIN","END"
"006852","99999","SENT","SW","SZ","","","+46817","+010350","+14200","",""
"007005","99999","CWOS 07005","","","","","-99999","-999999","-99999","20120127","20120127"

前两列包含气象站的代码,有时它们有前导零。当 pandas 在没有指定 dtype 的情况下导入它们时,它们会变成整数。这没什么大不了的,因为我可以遍历数据帧索引并用"%06d" % i 之类的东西替换它们,因为它们总是六位数,但你知道……这是懒惰的方式。

使用以下代码获取csv:

file = urllib.urlopen(r"ftp://ftp.ncdc.noaa.gov/pub/data/inventories/ISH-HISTORY.CSV")
output = open('Station Codes.csv','wb')
output.write(file.read())
output.close()

这一切都很好,但是当我去尝试阅读它时:

import pandas as pd
df = pd.io.parsers.read_csv("Station Codes.csv",dtype='USAF': np.str, 'WBAN': np.str)

import pandas as pd
df = pd.io.parsers.read_csv("Station Codes.csv",dtype='USAF': str, 'WBAN': str)

我收到一条令人讨厌的错误消息:

File "C:\Python27\lib\site-packages\pandas-0.11.0-py2.7-win32.egg\pandas\io\parsers.py", line 401, in parser
_f
    return _read(filepath_or_buffer, kwds)
  File "C:\Python27\lib\site-packages\pandas-0.11.0-py2.7-win32.egg\pandas\io\parsers.py", line 216, in _read
    return parser.read()
  File "C:\Python27\lib\site-packages\pandas-0.11.0-py2.7-win32.egg\pandas\io\parsers.py", line 633, in read
    ret = self._engine.read(nrows)
  File "C:\Python27\lib\site-packages\pandas-0.11.0-py2.7-win32.egg\pandas\io\parsers.py", line 957, in read
    data = self._reader.read(nrows)
  File "parser.pyx", line 654, in pandas._parser.TextReader.read (pandas\src\parser.c:5931)
  File "parser.pyx", line 676, in pandas._parser.TextReader._read_low_memory (pandas\src\parser.c:6148)
  File "parser.pyx", line 752, in pandas._parser.TextReader._read_rows (pandas\src\parser.c:6962)
  File "parser.pyx", line 837, in pandas._parser.TextReader._convert_column_data (pandas\src\parser.c:7898)
  File "parser.pyx", line 887, in pandas._parser.TextReader._convert_tokens (pandas\src\parser.c:8483)
  File "parser.pyx", line 953, in pandas._parser.TextReader._convert_with_dtype (pandas\src\parser.c:9535)
  File "parser.pyx", line 1283, in pandas._parser._to_fw_string (pandas\src\parser.c:14616)
TypeError: data type not understood

这是一个相当大的 csv(31k 行),所以可能与它有关?

【问题讨论】:

我发现使用 object 可以保持前导零:dtype='USAF': object, 'WBAN': object 来自这篇文章:***.com/questions/13293810/… str/np.str 不能正常工作有点奇怪......:S 我想知道这是否是一个错误,可能值得作为issue on github 发布。 是的,我也觉得这很奇怪,因为我可以在那里使用其他数字数据类型。 这基本上是两个月前的确切问题:github.com/pydata/pandas/issues/3209 似乎没有修复它的计划。 我想我记得 Wes 谈到过这个,我想他说在很多情况下使用 numpys(固定长度)字符串对象会非常昂贵......当你只是通过在常规字符串中(因为它在每个元素处使用 最大 字符串的内存)。我看看能不能找到。 【参考方案1】:

这是pandas dtype 猜测的问题。

Pandas 看到数字并猜测你希望它是数字。

为了让 pandas 不怀疑你的意图,你应该设置你想要的 dtype:object

pd.read_csv('filename.csv', dtype='leading_zero_column_name': object)

会成功的

更新,因为它可以帮助他人:

要将所有列作为str,可以这样做(来自评论):

pd.read_csv('sample.csv', dtype = str)

要将大多数或选择性列作为str,可以这样做:

# lst of column names which needs to be string
lst_str_cols = ['prefix', 'serial']
# use dictionary comprehension to make dict of dtypes
dict_dtypes = x : 'str'  for x in lst_str_cols
# use dict on dtypes
pd.read_csv('sample.csv', dtype=dict_dtypes)

【讨论】:

更多信息,read_csv 方法返回一个DataFrame. 并推断每个字段的默认值。通过显式声明 dtype,生成的 DataFrame 将正确处理字段。 @firelynx 对不起,它似乎不适用于read_excel【参考方案2】:

使用 Pandas 1,怎么样:

df.read_csv(..., dtype="my_confusing_col": "string")

请注意,将使用列 dtype string,它使用 pd.NA 来表示任何缺失值。当然会保留所有前导零。

【讨论】:

【参考方案3】:

在解析带有序列号的文件时,这个问题让我很头疼。由于未知原因,00794 和 000794 是两个不同的序列号。我最终想出了

converters = 'serial_number': str

【讨论】:

可能是因为我没想到:)【参考方案4】:

您可以将函数字典传递给converters,其中键是数字列索引。因此,如果您不知道列名是什么,您可以这样做(前提是您的列数少于 100)。

pd.read_csv('some_file.csv', converters=i: str for i in range(100))

【讨论】:

converters=dict.fromkeys(range(100), str) 怎么样?【参考方案5】:

如果您不希望字符串成为对象,您似乎必须指定字符串的长度。 例如:

dtype='USAF': '|S6'

我找不到这方面的参考资料,但我似乎记得 Wes 曾讨论过这个问题(也许在一次谈话中)。他建议 numpy 不允许“正确的”可变长度字符串(参见question/answer),并且使用最大长度来填充数组往往会导致空间效率低下(即使字符串很短它也会使用与最长字符串一样多的空间)。

正如@Wes 指出的那样,这也是一种情况:

dtype='USAF': object

同样有效。

【讨论】:

我建议'USAF': object

以上是关于熊猫 read_csv dtype 前导零的主要内容,如果未能解决你的问题,请参考以下文章

当我通过 skip_footer arg 时,Pandas read_csv 忽略列 dtypes

合并熊猫中的两个数据框

Pandas - 使用 read_csv 指定具有混合列数据的 dtype

模块“熊猫”没有属性“read_csv”

为 pandas.read_csv 指定正确的 dtypes 以获取日期时间和布尔值

如何加速熊猫 read_csv?