【问题标题】:Pandas format datetime with many different date typesPandas 使用许多不同的日期类型格式化日期时间
【发布时间】:2020-04-24 22:31:10
【问题描述】:

我正在尝试格式化“数据”列以制作带有日期的模式。

我的格式是:

1/30/20 16:00
1/31/2020 23:59
2020-02-02T23:43:02

这是数据框的代码。

import requests
import pandas as pd
import numpy as np
url = "https://github.com/CSSEGISandData/COVID-19/tree/master/csse_covid_19_data/csse_covid_19_daily_reports"
csv_only  = [i.split("=")[1][1:-1] for i in requests.get(url).text.split(" ") if '.csv' in i and 'title' in i]

combo = [pd.read_csv(url.replace("github","raw.githubusercontent").replace("/tree/","/")+"/"+f) for f in csv_only]

one_df = pd.concat(combo,ignore_index=True)

one_df["País"] = one_df["Country/Region"].fillna(one_df["Country_Region"])
one_df["Data"] = one_df["Last Update"].fillna(one_df["Last_Update"])

我尝试添加下面的代码,但它没有带来我想要的结果

pd.to_datetime(one_df['Data'])
one_df.style.format({"Data": lambda t: t.strftime("%m/%d/%Y")})

有什么帮助吗?

更新

这是完整的代码,但它不起作用。许多例外以不同的日期格式打印。

import requests
import pandas as pd
import numpy as np
from datetime import datetime
url = "https://github.com/CSSEGISandData/COVID-19/tree/master/csse_covid_19_data/csse_covid_19_daily_reports"
csv_only  = [i.split("=")[1][1:-1] for i in requests.get(url).text.split(" ") if '.csv' in i and 'title' in i]

combo = [pd.read_csv(url.replace("github","raw.githubusercontent").replace("/tree/","/")+"/"+f) for f in csv_only]

one_df = pd.concat(combo,ignore_index=True)

df = pd.DataFrame()
DATE_FORMATS = ["%m/%d/%y %H:%M", "%m/%d/%Y %H:%M", "%Y-%m-%dT%H:%M:%S", "%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M:%S", "%Y-%m-%d  %H:%M:%S"]

df["Região"] = one_df["Province/State"].fillna(one_df["Admin2"])
df["País"] = one_df["Country/Region"].fillna(one_df["Country_Region"])
df["Data"] = one_df["Last Update"].fillna(one_df["Last_Update"])
df["Confirmados"] = one_df["Confirmed"]
df["Mortes"] = one_df["Deaths"]
df["Recuperados"] = one_df["Recovered"]

def parse(x_):
    for fmt in DATE_FORMATS :
        try:
            tmp = datetime.strptime(x_, fmt).strftime("%m/%d/%Y")
            return tmp
        except ValueError:
            print(x_)

pd.to_datetime(df['Data'])
df['Data'] = df['Data'].apply(lambda x: parse(x))

#df['Data'].strftime('%m/%d/%Y')
#df['Data'] = df['Data'].map(lambda x: x.strftime('%m/%d/%Y') if x else '')

df.to_excel(r'C:\Users\guilh\Downloads\Covid2\Covid-19.xlsx', index=False,  encoding="utf8")
print(df)

【问题讨论】:

  • 假设日期列在csv中的格式相同,您可以尝试在将所有文件连接在一起之前对其进行转换?
  • pd.to_datetime(one_df['Data']) 为我工作。
  • 当我尝试格式化%d/%m/%Y 时,我得到ValueError: time data '1/22/2020 17:00' does not match format '%d/%m/%Y' (match)

标签: python pandas dataframe datetime


【解决方案1】:
from datetime import datetime
import pandas as pd

您可以将列表中所有可能的格式保存为 -

DATE_FORMATS = ["%Y-%m-%d %H:%M:%S", "%Y-%m-%dT%H:%M:%S", "%m/%d/%y %H:%M", "%m/%d/%Y %H:%M"]

定义一个循环遍历格式并尝试解析它的函数。 (修复了一个错误,其中print 语句应该在for 循环之外)

issues = set()
def parse(x_):
    for fmt in DATE_FORMATS:
        try:
            return datetime.strptime(x_, fmt).strftime("%m/%d/%Y")
        except ValueError:
            pass
    issues.add(x_)


sample = ["1/30/20 16:00", "1/31/2020 23:59", "2020-02-02T23:43:02"]

df = pd.DataFrame({'data': sample})
df['data'] = df['data'].apply(lambda x: parse(x))

assert df['Data'].isna().sum() == len(issues) == 0, "Issues observed, nulls observed in dataframe"

print("Done")

输出

         data
0  01/30/2020
1  01/31/2020
2  02/02/2020

如果df.apply() 遇到未在列表中定义的特定日期格式,它会简单地打印None,因为函数parse() 不会返回任何内容

【讨论】:

  • 如何添加一行来打印异常日期,以便将它们映射到 DATE_FORMATS?由于数据分析取决于精确的日期和国家/地区,因此我无法在日期上得到 None
  • except 子句中,您可以添加print(x_)(删除pass),这将以无法识别的格式打印日期。
  • 我有很多例外,2020-02-24T14:43:032020-02-24 14:43:03 和其他日期格式。我用我的完整代码更新了这个问题,包括你的这个答案,我用错了吗?
  • @guialmachado 所以,我的代码基本上有一个缺陷,所有的日期都被解析了,但是由于print(x_)语句的位置不正确而不必要地打印出来,请现在检查我编辑的代码.
【解决方案2】:

也在这里,让pd.to_datetime 推断格式可以解决问题:

import pandas as pd

s = pd.to_datetime(["1/30/20 16:00", "1/31/2020 23:59", "2020-02-02T23:43:02"])

print(s)
# DatetimeIndex(['2020-01-30 16:00:00', '2020-01-31 23:59:00',
#                '2020-02-02 23:43:02'],
#               dtype='datetime64[ns]', freq=None)

请注意,如果您的日期/时间格式通常首先提供日期(例如,30.1.2021 表示 2021 年 1 月 30 日),请设置关键字 dayfirst=True

【讨论】:

    猜你喜欢
    • 2020-05-27
    • 2019-09-14
    • 1970-01-01
    • 2017-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多