【问题标题】:Prevent pandas from automatically inferring type in read_csv防止 pandas 自动推断 read_csv 中的类型
【发布时间】:2012-08-19 12:41:24
【问题描述】:

我有一个 # 分隔的文件,其中包含三列:第一列是整数,第二列看起来像浮点数,但不是,第三列是字符串。我尝试使用pandas.read_csv

将其直接加载到 python 中
In [149]: d = pandas.read_csv('resources/names/fos_names.csv',  sep='#', header=None, names=['int_field', 'floatlike_field', 'str_field'])

In [150]: d
Out[150]: 
<class 'pandas.core.frame.DataFrame'>
Int64Index: 1673 entries, 0 to 1672
Data columns:
int_field          1673  non-null values
floatlike_field    1673  non-null values
str_field          1673  non-null values
dtypes: float64(1), int64(1), object(1)

pandas 尝试变得聪明并自动将字段转换为有用的类型。问题是我实际上并不希望它这样做(如果我这样做了,我会使用 converters 参数)。如何防止pandas自动转换类型?

【问题讨论】:

  • 这可能无法避免。 Pandas(以及更普遍的 NumPy)不支持整数的 NaN。由于从任何 CSV 中读取都为 NaN 留下了可能性,所以让它一直强制浮动可能是一个方便的选择。此外,您的类型似乎与您的打印输出相反。它肯定不会将floatlike输入转换为int64,尽管它可能将intlike输入转换为float64。
  • 我不相信列出的 dtypes 的顺序与列的顺序有任何关系,但是关于自动类型强制,这将是最不幸的。我的印象是无论类型如何,只要信息丢失,pandas 都会使用 NaN。
  • 是的,确实如此,但是该列将始终为 Object 类型。您可以拥有一个主要是 Ints 的 Object 列。但是,在许多情况下,NaN 会将其强制转换为浮点列。如果您首先创建一个对象列,然后用可能的 NaN 整数填充它,它将保持为对象。我认为如果你只是用那里的任何东西填充它,让 Pandas 来识别类型,它会为任何数字类型选择浮点数,而不是存在 NaN。这不仅仅是 Pandas 的限制,而是 NumPy 和 Python 的限制。我知道没有库提供支持 NaN 的 Int。
  • @EMS 不要忘记 numpy 还带有 MaskedArrays,它可以将数据标记为缺失/无效/随便...np.genfromtxt 自然支持MaskedArrays,这可能很有用.
  • @EMS 作为第二条评论,有人谈到为int ndarrays 添加一些类似NaN 的值。

标签: python pandas


【解决方案1】:

我计划在 Pandas 0.10 中即将进行的文件解析器引擎大修中添加显式列 dtype。我无法 100% 投入,但新基础设施的整合应该非常简单 (http://wesmckinney.com/blog/?p=543)。

【讨论】:

  • 期待!谢谢韦斯!
【解决方案2】:

我认为最好的办法是首先使用 numpy 将数据作为记录数组读取。

# what you described:
In [15]: import numpy as np
In [16]: import pandas
In [17]: x = pandas.read_csv('weird.csv')

In [19]: x.dtypes
Out[19]: 
int_field            int64
floatlike_field    float64  # what you don't want?
str_field           object

In [20]: datatypes = [('int_field','i4'),('floatlike','S10'),('strfield','S10')]

In [21]: y_np = np.loadtxt('weird.csv', dtype=datatypes, delimiter=',', skiprows=1)

In [22]: y_np
Out[22]: 
array([(1, '2.31', 'one'), (2, '3.12', 'two'), (3, '1.32', 'three ')], 
      dtype=[('int_field', '<i4'), ('floatlike', '|S10'), ('strfield', '|S10')])

In [23]: y_pandas = pandas.DataFrame.from_records(y_np)

In [25]: y_pandas.dtypes
Out[25]: 
int_field     int64
floatlike    object  # better?
strfield     object

【讨论】:

  • 这是个好主意。即使现在在 0.13.1 中也值得作为配方添加,因为 read_csv(dtype, converters, ...) 仍然有很多问题。
  • 如果你仍然想直接从 pandas 中读取,你也可以这样做: datatypes = {strfield': str, 'int_field' : int} pd.read_csv(path, dtypes=datatypes,...)
猜你喜欢
  • 2018-07-21
  • 1970-01-01
  • 1970-01-01
  • 2015-06-12
  • 1970-01-01
  • 2021-05-08
  • 1970-01-01
  • 2018-01-25
  • 1970-01-01
相关资源
最近更新 更多