python - 推断哪些列是日期时间

标签 python pandas

我有一个包含许多列的巨大数据框,其中许多列的类型是 datetime.datetime .问题是许多也有混合类型,例如 datetime.datetime值和 None值(以及其他可能无效的值):

0         2017-07-06 00:00:00
1         2018-02-27 21:30:05
2         2017-04-12 00:00:00
3         2017-05-21 22:05:00
4         2018-01-22 00:00:00
                 ...         
352867    2019-10-04 00:00:00
352868                   None
352869            some_string
Name: colx, Length: 352872, dtype: object

因此导致 object类型列。这可以通过 df.colx.fillna(pd.NaT) 解决.问题是数据框太大而无法搜索单个列。

另一种方法是使用 pd.to_datetime(col, errors='coerce') ,但是这将转换为 datetime许多包含数值的列。

我也可以做 df.fillna(float('nan'), inplace=True) ,虽然包含日期的列仍然是 object类型,仍然会有同样的问题。

我可以采用什么方法将那些值确实包含 datetime 的列转换为日期时间值,但也可以包含 None , 以及可能存在一些无效值(提到否则 pd.to_datetime/try 子句中的 except 会怎样)?有点像 pd.to_datetime(col) 的灵活版本

最佳答案

此函数会将列的数据类型设置为日期时间,如果列中的任何值与正则表达式模式(\d{4}-\d{2}-\d{2})+ (例如 2019-01-01 )。归功于这个关于如何 Search for String in all Pandas DataFrame columns and filter 的答案这有助于设置和应用面具。

def presume_date(dataframe):
    """ Set datetime by presuming any date values in the column
        indicates that the column data type should be datetime.

    Args:
        dataframe: Pandas dataframe.

    Returns:
        Pandas dataframe.

    Raises:
        None
    """
    df = dataframe.copy()
    mask = dataframe.astype(str).apply(lambda x: x.str.match(
        r'(\d{4}-\d{2}-\d{2})+').any())
    df_dates = df.loc[:, mask].apply(pd.to_datetime, errors='coerce')
    for col in df_dates.columns:
        df[col] = df_dates[col]
    return df

从使用建议开始工作 dateutil ,这可能会有所帮助。它仍在假设如果列中有任何类似日期的值,则该列应该是日期时间。我试图考虑更快的不同数据帧迭代方法。我认为这个答案在 How to iterate over rows in a DataFrame in Pandas 上很好地描述了他们。

请注意 dateutil.parser将当前日期或年份用于任何字符串,如“December”或“November 2019”,没有年份或日期值。

import pandas as pd
import datetime
from dateutil.parser import parse

df = pd.DataFrame(columns=['are_you_a_date','no_dates_here'])
df = df.append(pd.Series({'are_you_a_date':'December 2015','no_dates_here':'just a string'}), ignore_index=True)
df = df.append(pd.Series({'are_you_a_date':'February 27 2018','no_dates_here':'just a string'}), ignore_index=True)
df = df.append(pd.Series({'are_you_a_date':'May 2017 12','no_dates_here':'just a string'}), ignore_index=True)
df = df.append(pd.Series({'are_you_a_date':'2017-05-21','no_dates_here':'just a string'}), ignore_index=True)
df = df.append(pd.Series({'are_you_a_date':None,'no_dates_here':'just a string'}), ignore_index=True)
df = df.append(pd.Series({'are_you_a_date':'some_string','no_dates_here':'just a string'}), ignore_index=True)
df = df.append(pd.Series({'are_you_a_date':'Processed: 2019/01/25','no_dates_here':'just a string'}), ignore_index=True)
df = df.append(pd.Series({'are_you_a_date':'December','no_dates_here':'just a string'}), ignore_index=True)


def parse_dates(x):
    try:
        return parse(x,fuzzy=True)
    except ValueError:
        return ''
    except TypeError:
        return ''


list_of_datetime_columns = []
for row in df:
    if any([isinstance(parse_dates(row[0]),
                       datetime.datetime) for row in df[[row]].values]):
        list_of_datetime_columns.append(row)

df_dates = df.loc[:, list_of_datetime_columns].apply(pd.to_datetime, errors='coerce')

for col in list_of_datetime_columns:
    df[col] = df_dates[col]

如果您还想使用来自 dateutil.parser 的数据时间值,你可以添加这个:

for col in list_of_datetime_columns:
    df[col] = df[col].apply(lambda x: parse_dates(x))

关于python - 推断哪些列是日期时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58593565/

相关文章:

python - 如何获取多个动态文本文件的内容并将其存储在一个文本文件和mysql中 - Python 2.7?

python - python 中 "lambda"函数的模糊性

python - 检查 Pandas 列值包含在列表中并分配一个值

python - 如何根据数据框中的相似行(字符串)删除数据框的某些行

python - 在 python 中实现 Levenshtein 距离

python - 如何将 MSSQL 连接到 Django

python - Pandas 数据帧系列 : check if specific value exists

python - Pandas 中的 Groupby 或 Pivot?

python - 如何使用循环为数据帧提供顺序名称?

python - Python 中的 4D 密度图