当我尝试将csv文件导入数据帧时,pandas(0.13.1)忽略了dtype参数。有没有办法阻止pandas自己推断数据类型?
我正在合并多个CSV文件,有时客户将字母和pandas导入为字符串。当我尝试合并两个数据帧时,我得到一个错误,因为我正在尝试合并两种不同的类型。我需要存储为字符串的所有内容。
数据摘录:
|WAREHOUSE|ERROR|CUSTOMER|ORDER NO|
|---------|-----|--------|--------|
|3615 | |03106 |253734 |
|3615 | |03156 |290550 |
|3615 | |03175 |262207 |
|3615 | |03175 |262207 |
|3615 | |03175 |262207 |
|3615 | |03175 |262207 |
|3615 | |03175 |262207 |
|3615 | |03175 |262207 |
|3615 | |03175 |262207 |
导入行:
df = pd.read_csv("SomeFile.csv",
header=1,
skip_footer=1,
usecols=[2, 3],
dtype={'ORDER NO': str, 'CUSTOMER': str})
df.dtypes
输出:
ORDER NO int64
CUSTOMER int64
dtype: object
答案 0 :(得分:18)
Pandas 0.13.1默默地忽略了dtype
参数,因为c engine
不支持skip_footer
。这导致Pandas回退到不支持python engine
的{{1}}。
解决方案?使用dtype
converters
输出:
df = pd.read_csv('SomeFile.csv',
header=1,
skip_footer=1,
usecols=[2, 3],
converters={'CUSTOMER': str, 'ORDER NO': str},
engine='python')
保留原始文件中的前导0,并将所有数据存储为字符串。
答案 1 :(得分:7)
不幸的是,使用转换器或更新的pandas版本并不能解决总是确保read_csv不推断float64 dtype的更普遍的问题。对于pandas 0.15.2,下面的示例(包含带有NULL条目的十六进制表示的整数的CSV)表明,使用转换器来表示它们应该用于的名称,这会干扰dtype规范。
In [1]: df = pd.DataFrame(dict(a = ["0xff", "0xfe"], b = ["0xfd", None], c = [None, "0xfc"], d = [None, None]))
In [2]: df.to_csv("H:/tmp.csv", index = False)
In [3]: ef = pd.read_csv("H:/tmp.csv", dtype = {c: object for c in "abcd"}, converters = {c: lambda x: None if x == "" else int(x, 16) for c in "abcd"})
In [4]: ef.dtypes.map(lambda x: x)
Out[4]:
a int64
b float64
c float64
d object
dtype: object
对于all-NULL列,仅考虑指定的dtype对象。在这种情况下,float64值只能转换为整数,但根据鸽子原理,并非所有64位整数都可以表示为float64。
我为这个更一般的情况找到的最佳解决方案是让pandas将可能有问题的列读取为字符串,如已经涵盖的那样,然后使用需要转换的值转换切片(而不是映射列上的转换,如这将再次导致自动dtype = float64推断。)
In [5]: ff = pd.read_csv("H:/tmp.csv", dtype = {c: object for c in "bc"}, converters = {c: lambda x: None if x == "" else int(x, 16) for c in "ad"})
In [6]: ff.dtypes
Out[6]:
a int64
b object
c object
d object
dtype: object
In [7]: for c in "bc":
.....: ff.loc[~pd.isnull(ff[c]), c] = ff[c][~pd.isnull(ff[c])].map(lambda x: int(x, 16))
.....:
In [8]: ff.dtypes
Out[8]:
a int64
b object
c object
d object
dtype: object
In [9]: [(ff[c][i], type(ff[c][i])) for c in ff.columns for i in ff.index]
Out[9]:
[(255, numpy.int64),
(254, numpy.int64),
(253L, long),
(nan, float),
(nan, float),
(252L, long),
(None, NoneType),
(None, NoneType)]
据我所知,至少达到版本0.15.2,在这种情况下无法避免字符串值的后处理。
答案 2 :(得分:0)
就像上面Ripster的回答一样,解决了OP的问题。但是对我来说,尽管这对某些人来说似乎很明显,但我的问题是CVS中的标头/列名全为大写,而在代码中的dtype = {...}中却以小写表示。将它们全部切换为大写,并且read_csv停止忽略我的显式键入。 SQL是我的母语,在大多数情况下,列名的大小写无关紧要。有几个小时我不会回来...