【问题标题】:Ignore string data that does not match a certain format when calculating "min" with Pandas用 Pandas 计算“min”时忽略不匹配特定格式的字符串数据
【发布时间】:2016-12-25 18:39:13
【问题描述】:

我有一个 DataFrame 列“日期时间”,其值采用这种格式:

'2016-08-01 13:43:35'

我想找到最小值和最大值。问题是某些行缺少时间值,因此它们看起来像这样:

'2016-07-29 '

在计算最小值和最大值时如何排除缺失数据的行?

这是我找到最小值的方法:

min_ = df['datetime'].min()

我试图找到的最小值是包含两者的最早日期/时间组合。因此,例如从我的数据中:

'7/29/2016 11:02:38' 将是所需的值。

【问题讨论】:

  • 您试图找到的最小值是多少?
  • @Nikil,我已经编辑了我上面的问题以包含它。

标签: python pandas


【解决方案1】:

您可以将具有特定格式的值转换为日期时间,其余的将是 NaT。如果您在结果系列中取最小值,它将忽略 NaT。

df['datetime'] = ['2016-08-01 13:43:35', '2016-06-01 13:43:35', '2013-08-01 13:43:35',
                  '2016-07-29  ']
df
Out: 
              datetime
0  2016-08-01 13:43:35
1  2016-06-01 13:43:35
2  2013-08-01 13:43:35
3         2016-07-29  


pd.to_datetime(df['datetime'], format='%Y-%m-%d %H:%M:%S', errors='coerce')
Out: 
0   2016-08-01 13:43:35
1   2016-06-01 13:43:35
2   2013-08-01 13:43:35
3                   NaT
Name: datetime, dtype: datetime64[ns]

pd.to_datetime(df['datetime'], format='%Y-%m-%d %H:%M:%S', errors='coerce').min()
Out: Timestamp('2013-08-01 13:43:35')

【讨论】:

    【解决方案2】:

    由于您的日期字符串具有递减的数量级(即年 --> 月 --> ...),因此实际上不需要转换日期时间对象。

    此外,由于您的日期字符串都应该是固定宽度的,您真正需要做的就是删除缺少值的行,然后直接比较日期字符串。

    df = pd.DataFrame({'datetime': ['2016-08-01 13:43:35', '2016-06-01 13:43:35', '2013-08-01 13:43:35', '2016-07-29  ']})
    
    min_dt = df[df.datetime.str.len() == 19].min()
    print min_dt
    # 2013-08-01 13:43:35
    
    max_dt = df[df.datetime.str.len() == 19].max()
    print max_dt
    # 2016-08-01 13:43:35
    

    [编辑] 由于运行时间的话题出现在 cmets 中,我做了一些 %timeit 测试,发现保留日期字符串(而不是使用 to_datetime)大约快 20 倍。但是对于 1M 行,这两种方法的速度都可以接受。

    print data[0:4] # Data list of 1M date strings.
    # >>> ['01/01/2015 00:00:00', '01/01/2015 00:05:00', '01/01/2015 00:10:00', '01/01/2015 00:15:00']
    
    print len(data)
    # >>> 1047870
    
    df = pd.DataFrame({'datetime': data})
    df2 = pd.DataFrame({'datetime': data})
    
    %timeit -n5 d=pd.to_datetime(df['datetime'], format='%m/%d/%Y %H:%M:%S', errors='coerce').min()
    # >>> 5 loops, best of 3: 5 s per loop
    
    %timeit -n5 df2[df2['datetime'].str.len() == 19].min()
    # >>> 5 loops, best of 3: 232 ms per loop
    

    【讨论】:

    • 感谢您的反馈。在我的情况下,您的解决方案是从数据框中的其他列返回多个值,而不是从“日期时间”列返回多个值。
    • 这不是一个非常昂贵的操作。这是一次性操作,在具有 10m 行的数据帧上只需几秒钟。另一方面,一旦转换,找到日期时间变量的最小值/最大值会更快。当类型为 datetime 时,聚合或总结会容易得多。
    • 我记得去年对我的一个项目进行了概要分析,发现大部分运行时间是由于to_datetime 进程造成的。我得调查一下。
    • @ayhan 玩了timeit,今天学到了一些东西。当您使用 format 参数时,to_datetime 的执行速度大约快 50 倍。我一直认为to_datetime 很昂贵,因为我第一次在数百万行上使用它时没有指定format!我将编辑我的答案。
    • 我认为它受无效条目数量的影响很大。当我用 1m 条目计时(25% 无效)时,结果是 280 毫秒对 478 毫秒。当只有前 3 个有效时,它是 226ms vs 1.16s。也可能因版本不同而有差异? imgur.com/a/WDgbp
    猜你喜欢
    • 2021-02-23
    • 2022-11-14
    • 1970-01-01
    • 2019-04-05
    • 1970-01-01
    • 1970-01-01
    • 2013-11-19
    • 2012-08-07
    • 2018-10-08
    相关资源
    最近更新 更多