Python Pandas 推断列数据类型

21

我正在将JSON文件读入数据框中。数据框可能具有一些字符串(即object类型)列、一些数值型(int64和/或float64)列和一些日期时间类型列。当数据被读入时,数据类型通常是不正确的(例如日期时间、int和float通常会被存储为"object"类型)。我想报告这种可能性。(例如,一个列在数据框中作为"object"(字符串)存在,但实际上它是一个"datetime")。

我的问题是,当我使用pd.to_numericpd.to_datetime时,它们都会评估并尝试转换列,并且很多时候最终取决于我哪一个调用最后一个……(我曾经要使用convert_objects(),但那个已经被弃用了,所以想要更好的选择)。

我正在使用以下代码来评估数据框列(我意识到下面很多内容都是冗余的,但出于可读性的考虑,我这样写的):

try:
   inferred_type = pd.to_datetime(df[Field_Name]).dtype
   if inferred_type == "datetime64[ns]":
      inferred_type = "DateTime"
except:
   pass
try:
   inferred_type = pd.to_numeric(df[Field_Name]).dtype
   if inferred_type == int:
      inferred_type = "Integer"
   if inferred_type == float:
      inferred_type = "Float"
except:
   pass

2
很遗憾它已经被弃用了。这是一个非常优秀的方法。 - Andy Hayden
convert_objects 已被废弃,请使用infer_objects代替。infer_objects - itzjustricky
6
@itzjustricky 的意思是,infer_objects() 方法甚至无法将 ['1', '2', '3'] 识别为数值型数据。执行 pd.DataFrame(['1', '2', '3']).infer_objects().dtypes 会返回 "object" 类型。 - PabTorre
convert_objects可能会被淘汰,但是你可以使用infer_objectsconvert_dtypes,它们可能会很有用。 - David Siret Marqués
7个回答

15

我遇到了同样的问题,需要确定先前不知道类型的传入数据列类型(在我的情况下是来自数据库读取)。我在SO上没有找到好的答案,也没有通过查看Pandas源代码解决。我使用了这个函数来解决:

def _get_col_dtype(col):
        """
        Infer datatype of a pandas column, process only if the column dtype is object. 
        input:   col: a pandas Series representing a df column. 
        """

        if col.dtype == "object":
            # try numeric
            try:
                col_new = pd.to_datetime(col.dropna().unique())
                return col_new.dtype
            except:
                try:
                    col_new = pd.to_numeric(col.dropna().unique())
                    return col_new.dtype
                except:
                    try:
                        col_new = pd.to_timedelta(col.dropna().unique())
                        return col_new.dtype
                    except:
                        return "object"
        else:
            return col.dtype

6
在Pandas API中,实际上有一个函数可以做出相当不错的工作。
import pandas as pd

infer_type = lambda x: pd.api.types.infer_dtype(x, skipna=True)
df.apply(infer_type, axis=0)


# DataFrame with column names & new types

df_types = pd.DataFrame(df.apply(pd.api.types.infer_dtype, axis=0)).reset_index().rename(columns={'index': 'column', 0: 'type'})

http://pandas.pydata.org/pandas-docs/stable/generated/pandas.api.types.infer_dtype.html#pandas.api.types.infer_dtype

该文档介绍了Pandas中的infer_dtype()函数,它可以推断给定数据的最适合的数据类型。推断规则与正常创建Series/DataFrame时相同。

如果需要将数据转换为整数或浮点数,请考虑使用to_numeric函数。
例如:df['amount'] = pd.to_numeric(df['amount'], errors='ignore')


8
似乎对我没有作用,即使有一些整数、浮点数和布尔列,也返回了所有字符串。 - wordsforthewise

5
这是我觉得最好的方法:

    df.convert_dtypes()

1
简单易用,适合我的需求。 - Nand0san

3

解决让它推断出数据类型的一个方法是使用 StringIO 将数据写入 CSV 文件,然后再读取回来。


1

根据BeigeBruceWayne的回答进行工作

df_types = pd.DataFrame(df_final.apply(pd.api.types.infer_dtype, axis=0)).reset_index().rename(columns={'index': 'column', 0: 'type'})

loop_types = df_types.values.tolist()

for col in loop_types:
    if col[1] == 'mixed':
        pass
    else:
        if col[1] == 'decimal':
            data_type = 'float64'
        elif col[1] == 'string':
            data_type = 'str'
        elif col[1] == 'integer':
            data_type = 'int'
        elif col[1] == 'floating':
            data_type = 'float64'
        elif col[1] == 'date':
            data_type = 'datetime64'
        else:
            data_type = col[1]
        df_final[col[0]] = df_final[col[0]].astype(data_type)


0

尝试例如

df['field_name'] = df['field_name'].astype(np.float64)

(假设 import numpy as np

谢谢。我如何使用上述策略检查日期时间? - Calamari
df['field_name'] = pd.to_datetime(df['field_name']) - zebralove79
仍然遇到相同的问题。列似乎可以被评估为日期时间和浮点类型。 - Calamari
等等,你是在尝试将一列转换以查看是否会出现错误吗?你是在暗示你不知道数据列的类型吗?这很尴尬;我建议你先定义好数据集。例如,Epoch时间中的日期可能看起来像int,因此转换为int或datetime都可以。 - zebralove79
1
是的,这是我的方法(因为没有更好的解决方案)......我认为这不是做事情的最佳方式,但我根本无法控制将读入数据帧的数据集(因此出现了问题)。 欢迎任何其他建议! - Calamari

0

另外一种方式:Pandas允许您在创建数据框时明确定义数据类型。您可以传入一个包含列名作为键和所需数据类型作为值的字典。

标准构造函数文档

或者在导入到数据框后转换列的类型

例如:df ['field_name'] = df ['field_name'] .astype(np.date_time)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接