【问题标题】:Pandas: Remove rows whose date does not follow specified formatPandas:删除日期不符合指定格式的行
【发布时间】:2014-02-28 16:10:02
【问题描述】:

在我的数据集中,我有一个日期列,其中的数据是混合格式的。

  • 有些行只有YYYY(例如2009
  • 其他人有MMM-YY(例如Jan-08
  • 还有一些人有完整的约会MM/DD/YYYY(例如01/15/2006

如何删除不遵循MM/DD/YYYY 格式的条目?我不太确定从哪里开始。

下面,我将数据的.head() 提供为dict

{'Collection Date': {0: '2001',
  1: '2002',
  2: '2006',
  3: '2/19/2006',
  4: '2/28/2006'},
 'Complete Genome': {0: 'No', 1: 'No', 2: 'No', 3: 'No', 4: 'No'},
 'Country': {0: 'Egypt', 1: 'Egypt', 2: 'Egypt', 3: 'Egypt', 4: 'Egypt'},
 'Flu Season': {0: '-N/A-', 1: '-N/A-', 2: '-N/A-', 3: '-N/A-', 4: '-N/A-'},
 'Host Species': {0: 'IRD:Human',
  1: 'IRD:Human',
  2: 'IRD:Bird/Avian',
  3: 'IRD:Chicken/Avian',
  4: 'IRD:Avian'},
 'Protein Name': {0: 'NA', 1: 'NA', 2: 'NA', 3: 'NA', 4: 'HA'},
 'Segment': {0: 6, 1: 6, 2: 6, 3: 6, 4: 4},
 'Segment Length': {0: 1428, 1: 1449, 2: 1441, 3: 1363, 4: 1707},
 'Sequence Accession': {0: 'AJ457944',
  1: 'AJ457943',
  2: 'GU050304',
  3: 'GQ184251',
  4: 'KF178948'},
 'State/Province': {0: '-N/A-',
  1: '-N/A-',
  2: '-N/A-',
  3: '-N/A-',
  4: '-N/A-'},
 'Strain Name': {0: '(A/Egypt/84/2001(H1N2))',
  1: '(A/Egypt/96/2002(H1N2))',
  2: 'A/avian/Egypt/920431/2006(H9N2)',
  3: 'A/chicken/Egypt/06207-NLQP/2006(H5N1)',
  4: 'A/chicken/Egypt/0626/2006'},
 'Subtype': {0: 'H1N2', 1: 'H1N2', 2: 'H9N2', 3: 'H5N1', 4: 'H5N1'}}

【问题讨论】:

  • 使用正则表达式拆分数据然后使用 strptime IMO 应用一些日期解析可能更好,我想不出更简单的方法
  • @EdChum 是对的,这样做非常棘手(而提高效率的熊猫不会)。
  • 我可以尝试的另一种方法是,如果我要简单地删除不符合 MM/DD/YYYY 格式的数据。那可能吗?我也会修改问题。
  • @ericmjl 是的,你可以这样做,再次使用正则表达式
  • @ericmjl 我刚刚阅读了您的新要求并更新了我的答案以过滤不是MM/DD/YYYY 的日期,在您的情况下,使用字符串长度比凌乱的正则表达式字符串更容易和简单

标签: python date datetime pandas


【解决方案1】:

您可以使用pd.to_datetimeerrors='coerce' 选项将无效日期转换为NaT,然后使用dropna() 过滤掉NaTs

例子:

>>> df = pd.DataFrame({'date':['01/03/1987', '2003', 'Jan-08', '31/01/2010', '2/13/2016'],'value':range(5)})
>>> df
         date  value
0  01/03/1987      0
1        2003      1
2      Jan-08      2
3  31/01/2010      3
4   2/13/2016      4

格式:DD/MM/YYYY

>>> pd.to_datetime(df['date'], format='%d/%m/%Y', errors='coerce')
0   1987-03-01
1          NaT
2          NaT
3   2010-01-31
4          NaT
>>> df['date'] = pd.to_datetime(df['date'], format='%d/%m/%Y', errors='coerce')
>>> df.dropna()
        date  value
0 1987-03-01      0
3 2010-01-31      3

【讨论】:

    【解决方案2】:

    如果您的日期只是 YYYY 或 MMM/YYYY 或 MM/DD/YYYY,那么您可以利用 MM/DD/YYYY 是一个字符串,而不是应用正则表达式来匹配 MM/DD/YYYY长度 10:

    In [8]:
    
    import pandas as pd
    
    pd.set_option('display.notebook_repr_html', False)
    df = pd.DataFrame({'date':['01/03/1987', '2003', 'Jan-08', '31/01/2010']})
    df
    Out[8]:
             date
    0  01/03/1987
    1        2003
    2      Jan-08
    3  31/01/2010
    
    [4 rows x 1 columns]
    In [9]:
    
    df.ix[df.date.str.len() !=10]
    Out[9]:
         date
    1    2003
    2  Jan-08
    
    [2 rows x 1 columns]
    

    然后你就可以使用to_datetime:

    In [16]:
    
    df1 = df.ix[df.date.str.len() !=10]
    df1
    Out[16]:
         date
    1    2003
    2  Jan-08
    
    [2 rows x 1 columns]
    In [17]:
    
    df1.date = pd.to_datetime(df1.date)
    df1
    Out[17]:
                     date
    1 2003-01-01 00:00:00
    2 2014-01-08 00:00:00
    
    [2 rows x 1 columns]
    

    如果您想使用 regexp 进行过滤,仅出于完整性考虑:

    df.ix[~df.date.str.contains('(\d{2})[/](\d{2})[/](\d{4})')]
    

    可以,请注意~,这是一个否定

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-16
      • 1970-01-01
      • 2022-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-18
      相关资源
      最近更新 更多