【问题标题】:Unexpected results of min() and max() methods of Pandas series made of Timestamp objects由 Timestamp 对象构成的 Pandas 系列的 min() 和 max() 方法的意外结果
【发布时间】:2012-10-10 01:51:08
【问题描述】:

我在进行基本数据修改时遇到了这种行为,如下例所示:

In [55]: import pandas as pd
In [56]: import numpy as np
In [57]: rng = pd.date_range('1/1/2000', periods=10, freq='4h')
In [58]: lvls = ['A','A','A','B','B','B','C','C','C','C']
In [59]: df = pd.DataFrame({'TS': rng, 'V' : np.random.randn(len(rng)), 'L' : lvls})

In [60]: df
Out[60]: 
   L                  TS         V
0  A 2000-01-01 00:00:00 -1.152371
1  A 2000-01-01 04:00:00 -2.035737
2  A 2000-01-01 08:00:00 -0.493008
3  B 2000-01-01 12:00:00 -0.279055
4  B 2000-01-01 16:00:00 -0.132386
5  B 2000-01-01 20:00:00  0.584091
6  C 2000-01-02 00:00:00 -0.297270
7  C 2000-01-02 04:00:00 -0.949525
8  C 2000-01-02 08:00:00  0.517305
9  C 2000-01-02 12:00:00 -1.142195

问题:

In [61]: df['TS'].min()
Out[61]: 31969-04-01 00:00:00

In [62]: df['TS'].max()
Out[62]: 31973-05-10 00:00:00

虽然这看起来不错:

In [63]: df['V'].max()
Out[63]: 0.58409076701429163

In [64]: min(df['TS'])
Out[64]: <Timestamp: 2000-01-01 00:00:00>

在 groupby 之后聚合时:

In [65]: df.groupby('L').min()
Out[65]: 
             TS         V
L                        
A  9.466848e+17 -2.035737
B  9.467280e+17 -0.279055
C  9.467712e+17 -1.142195

In [81]: val = df.groupby('L').agg('min')['TS']['A']
In [82]: type(val)
Out[82]: numpy.float64

显然在这种特殊情况下,它与使用频率日期时间索引作为 pd.Series 函数的参数有关:

In [76]: rng.min()
Out[76]: <Timestamp: 2000-01-01 00:00:00>

In [77]: ts = pd.Series(rng)
In [78]: ts.min()
Out[78]: 31969-04-01 00:00:00

In [79]: type(ts.min())
Out[79]: numpy.datetime64

但是,我最初的问题是通过 pd.read_csv() 从字符串中解析的时间戳系列的最小值/最大值

我做错了什么?

【问题讨论】:

  • 你使用的是什么版本的 Numpy? 1.6 中时间戳的表示存在问题。
  • 它都在 Numpy 1.6.2 和 Pandas 0.9.0 下,通过 MacPorts 维护。按照您的提示,我找到了similar problem reports,只是想弄清楚它们与我的情况有何关系。
  • 顺便说一句,Meteore,您(或其他任何人)能够复制这种行为吗?

标签: python pandas timestamp data-munging


【解决方案1】:

正如@meteore 指出的,这是 NumPy 1.6.x 中 np.datetime64 类型的字符串 repr 的问题。 基础数据,应该仍然是正确的。要解决此问题,您可以执行以下操作:

In [15]: df
Out[15]: 
   L                  TS         V
0  A 2000-01-01 00:00:00  0.752035
1  A 2000-01-01 04:00:00 -1.047444
2  A 2000-01-01 08:00:00  1.177557
3  B 2000-01-01 12:00:00  0.394590
4  B 2000-01-01 16:00:00  1.835067
5  B 2000-01-01 20:00:00 -0.768274
6  C 2000-01-02 00:00:00 -0.564037
7  C 2000-01-02 04:00:00 -2.644367
8  C 2000-01-02 08:00:00 -0.571187
9  C 2000-01-02 12:00:00  1.618557

In [16]: df.TS.astype(object).min()
Out[16]: datetime.datetime(2000, 1, 1, 0, 0)

In [17]: df.TS.astype(object).max()
Out[17]: datetime.datetime(2000, 1, 2, 12, 0)

【讨论】:

  • 是的,但是 min/max 的结果应该被装箱为时间戳。我会打开一个问题:github.com/pydata/pandas/issues/2083
  • 谢谢!所以我应该绕过时间戳表示,直到问题得到解决?只有在这种特殊情况下,还是可以概括这种滋扰?
  • 时间戳没问题。问题是 numpy.datetime64 表示。 Timestamp 实际上是 python datetime 的子类,正如@Wes_Mckinney 所提到的,我们将进行修复以将 numpy.datetime64 返回值装箱为 Timestamp,以便它可以正确表示。
  • datetime64 的问题比看起来更隐蔽: In [5]: pd.Timestamp(df.TS.min()) Out[5]:
  • 这个问题解决了吗?我无法从系列中获取最大时间戳。
猜你喜欢
  • 2016-05-21
  • 1970-01-01
  • 2017-10-16
  • 2021-09-30
  • 1970-01-01
  • 2022-12-13
  • 2021-05-05
  • 2016-05-05
  • 2021-10-19
相关资源
最近更新 更多