【问题标题】:Parse multiple date formats into a single format-further question将多种日期格式解析为一个格式-进一步的问题
【发布时间】:2021-01-26 20:10:26
【问题描述】:

更新:问题现已解决:)

我之前问过一个similar question。这个答案太好了。但是现在,数据集变得更加复杂了。

根据原来的答案,我试过这样:

 fmt=['%Y-%m-%d', '%d-%m-%Y', '%d/%m/%Y','%Y-%d-%m', '%Y-%d-%b', '%d-%b-%Y', 
  '%d/%b/%Y','Year: %d; month','month: %d;Year','%Y','%b %d %Y','%b %Y %d',
     '%Y/%m/%d','%Y/%d/%m','%Y%m']

 dfs = [pd.to_datetime(df['Date'], format=f, errors='coerce') for f in fmt]

 df['Date']= pd.concat(dfs, axis=1).bfill(axis=1).iloc[:, 0]

它在 df.date 列中给了我超过 4000 个 NaN 值。如果我删除所有这些 NaN 值,那就太多了。当我追踪日期列时,这些 NaN 值是由这些行引起的:

20050
2014/17/0
2006/0/5
2005-3-0
2006-18-0
2004/24/7

关于我应该如何处理它们的任何想法?我正在考虑用零到一替换那些月份/日期,如下所示:

 20500           =====> 2005-01-01
 2014/17/0       =====> 2004-01-17
 2006/0/5        =====> 2006-01-05
 2005-3-0        =====> 2005-03-01
 2006-18-0       =====> 2006-01-18
 

注意:日期的某些行是年/月/日格式,而其他行可能是年/日/月或简单的 YearDate

感谢您的帮助!

[![在此处输入图片描述][2]][2]

以下是一些打印出来的日期格式:

2002-11-25
2001-11-25
2002-9-27
2001-2-24
2002-9-20
2001-5-3
2002-2-28
200510
2004/19/10
2006-11-01
2004/22/3
20055
2004/28/4
2006-6-01
20057
20050
2006-10-01
2004/17/0
2006-6-01
2006-3-01
2001-4-4
2001-6-19
2003/16/11
20054
20065
20057
2006-2-01
2003/0/1
2002-1-27
20057
2006-5-01
20065
2006-0-01
2006-9-01
2002-6-28
20054
2001-1-25
2006-0-01
2006-3-01
2006-1-01
2006-1-01
2004/5/2
2003/3/4
2002-10-13
2006-6-01
2004/24/1
2002-11-11
2001-4-9
2003/21/4
2002-4-1
2004/24/7

通过 jezrael 的解决方案,我成功地将 NaT 值从 4000 多行减少到仅 300 行左右。这 300 行中的数据格式如下:

        Date        Date1
238     2001-01-0     NaT
249     2001-1-0      NaT
277     2001-2-0      NaT
506     2002-1-0      NaT
535     2002-4-0      NaT    
58510   2001-1-0      NaT
58516   2001-1-0      NaT
58779   2002-3-0      NaT
58888   2001-3-0      NaT
58889   2002-8-0      NaT

【问题讨论】:

    标签: python pandas date


    【解决方案1】:

    存在无效日期的问题,主要是因为0 正在像1 一样处理。所以解决方案是替换这个值,$ 是匹配字符串的结尾:

    d = {'/0$':'/01','/0/':'/01/','-0-':'-01-'}
    df['Date'] = df['Date'].replace(d, regex=True)
    
    #for replace formats like 20050 to 200501
    m = df['Date'].str.len().eq(5) & df['Date'].str.endswith('0')
    
    df['Date'] = df['Date'].mask(m, df['Date'] + '1')
    

    您仍然可以在原始解决方案中寻找不匹配的值,例如用于检查数据:

    fmt=['%Y-%m-%d', '%d-%m-%Y', '%d/%m/%Y','%Y-%d-%m', '%Y-%d-%b', '%d-%b-%Y', 
      '%d/%b/%Y','Year: %d; month','month: %d;Year','%Y','%b %d %Y','%b %Y %d',
         '%Y/%m/%d','%Y/%d/%m','%Y%m']
    
    dfs = [pd.to_datetime(df['Date'], format=f, errors='coerce') for f in fmt]
    
    df['Date1']= pd.concat(dfs, axis=1).bfill(axis=1).iloc[:, 0]
     
    df = df[df['Date1'].isna()]
    print (df)
             Date Date1
    15      20050   NaT
    17  2004/17/0   NaT
    27   2003/0/1   NaT
    32  2006-0-01   NaT
    37  2006-0-01   NaT
    

    【讨论】:

    • 谢谢@jezrael。我应该如何运行它?使用该 fmt,所有无效格式都转换为 NaT。我应该在运行 fmt 之前先运行您的上述代码吗?
    • 在我或@Quang 解决方案之前。
    • 感谢@jezrael,根据您的建议,NaT 值已经从 4000 多减少到 1100。当整个数据集的长度超过 450,000 时,我想我可以删除剩下的 1100 NaT行:)或者你有什么建议
    • 完美。谢谢@jezrael
    • 剩余错误日期的天数为零。我想可以通过再添加一行 m = df['Date'].str.len().eq(7) 来修复它。但是有些月份有两位数,有些只有一位数,所以我会忽略那些:)
    【解决方案2】:

    你最好使用fillna

    # initialize with all `nan`
    out = pd.Series(pd.NaT, df.index)
    
    # list of formats
    fmt=['%Y-%m-%d', '%d-%m-%Y', '%d/%m/%Y','%Y-%d-%m', '%Y-%d-%b', '%d-%b-%Y', 
    '%d/%b/%Y','Year: %d; month','month: %d;Year','%Y','%b %d %Y','%b %Y %d',
     '%Y/%m/%d','%Y/%d/%m','%Y%m']
    
    # loop through format,
    # update the series with valid dates for that format
    for f in fmt:
        out = out.fillna(pd.to_datetime(df['Date'], format=f, errors='coerce'))
    
    df['Date'] = out
    

    【讨论】:

    • 感谢广晃。当我使用fillna时,它的价值是多少?或者,我可以试试。一分钟:)
    • 在第二个注释中,您的示例数据包含所有格式的无效日期。所以你会得到所有的NaN 值。如果这是故意的,我将删除此答案。
    • 我想最小化这些 NaN 值@Quang Hoang。我确实知道某些格式无效,例如 2004/24/7。这很奇怪,运行您的代码后,我仍然得到几乎相同数量的 NaN 值。在你的回答中,第一行,我应该写 df.index 还是 df.date.index?
    • df.indexdf.date.index 是一回事。然而,2004/24/7 实际上是您示例中唯一不是 NaN 的东西。
    • 嗨!我需要重新运行并再次检查。这可能需要一些时间。因为现在 NaT 仍然存在。如果它解决了问题,我会接受答案。非常感谢您的帮助!
    猜你喜欢
    • 2020-07-04
    • 2019-11-10
    • 1970-01-01
    • 1970-01-01
    • 2013-01-09
    • 1970-01-01
    • 2020-09-14
    • 2014-03-04
    • 1970-01-01
    相关资源
    最近更新 更多