pandas自动推断日期类型

构建一个csv文件:

import pandas as pd
pd.DataFrame(data={"datetime": ["1999-10-10 10:10:10"] * 150, "index": range(150)}).to_csv('/tmp/test.csv', index=False)

查看/tmp/test.csv内容:

datetime,index
1999-10-10 10:10:10,0
1999-10-10 10:10:10,1
1999-10-10 10:10:10,2
1999-10-10 10:10:10,3
...

读取这个csv文件:

df = pd.read_csv('/tmp/test.csv')
print(df.dtypes)

输出:

datetime    object
index        int64
dtype: object

默认pandas并不会自动做日期类型数据的识别,datatime被识别成字符串, 使用pandas自带的推断日期方法进行推断:

df = pd.read_csv('/tmp/test.csv', infer_datetime_format=True, parse_dates=['datetime'])
print(df.dtypes)

输出:

datetime    datetime64[ns]
index                int64
dtype: object

这种方法的问题在于需要事先知道列名,指定从哪些列里面推断这些列是不是日期类型,而期望pandas自动识别哪些是日期列就像识别哪些是float列一样。

查看一下pandas的推断方法:

infer_datetime_format: bool, default False
If True and parse_dates is True for a column, try to infer the
datetime format based on the first datetime string. If the format
can be inferred, there often will be a large parsing speed-up.

它的推断方式使用第一个不为空的值尝试转换为日期列,如果能成功把此列当成日期列处理,否则不是。

仿照这个思路,可以来实现自动识别哪些是日期列:

  1. 正常读取pd.read_csv()
  2. 读取出来的df挑出来是object类型的列
  3. 对object类型的列取前100行非空的行,尝试转换成日期,如果全部成功则认为该列是日期类型

这个方法的优势:

  1. 不需要事先知道csv数据中的列
  2. 使用前100行数据比前1行数据更靠谱,而且性能损失不大

实现参考:

df = pd.read_csv('/tmp/test.csv')

def get_categorical_cols(df: pd.DataFrame):
    c_list = []
    for k, v in df.dtypes.items():
        if 'object' in v.name:
            c_list.append(k)
    return c_list


def parse_date(series: pd.Series):
    format = "%Y-%m-%d %H:%M:%S"  # Now only support one format
    # 1. take top 100 non-empty values
    INFER_TOP_N = 100
    series_non_empty = series.dropna()[: INFER_TOP_N]

    # 2. if these value all datetime value infer it as datetime nor object
    for item in series_non_empty:
        try:
            if isinstance(item, str):
                pd.datetime.strptime(item, format)
            else:
                return series
        except Exception as e:
            return series

    # 3. infer as datetime
    return pd.to_datetime(series, format=format)


categorical_cols = get_categorical_cols(df)

for c in categorical_cols:
    df[c] = parse_date(df[c])

print(df.dtypes)

输出:

datetime    datetime64[ns]
index                int64
dtype: object

参考:

原文地址:https://www.cnblogs.com/oaks/p/14298157.html