为什么以下数据框中的 datetime = 0 的差异?

数据挖掘 Python 熊猫 麻木的 数据框
2022-03-07 20:10:59

我面临的这个问题很简单,但很奇怪,一直困扰着我。

我有一个数据框如下:

df['datetime'] = df['datetime'].dt.tz_convert('US/Pacific')
df.head()

        vehicle_id  trip_id                                 datetime    
6760612 1000500 4f874888ce404720a203e36f1cf5b716    2017-01-01 10:00:00-08:00       
6760613 1000500 4f874888ce404720a203e36f1cf5b716    2017-01-01 10:00:01-08:00    
6760614 1000500 4f874888ce404720a203e36f1cf5b716    2017-01-01 10:00:02-08:00      
6760615 1000500 4f874888ce404720a203e36f1cf5b716    2017-01-01 10:00:03-08:00       
6760616 1000500 4f874888ce404720a203e36f1cf5b716    2017-01-01 10:00:04-08:00   

我试图找出数据时间差异如下(以两种不同的方式):

df['datetime_diff'] = df['datetime'].diff()

df['time_diff'] = (df['datetime'] - df['datetime'].shift(1)).astype('timedelta64[s]')

对于特定的trip_id,我的结果如下:

df[trip_frame['trip_id'] == '4f874888ce404720a203e36f1cf5b716'][['datetime','datetime_diff','time_diff']].head()

                   datetime         datetime_diff   time_diff
6760612 2017-01-01 10:00:00-08:00   NaT             NaN
6760613 2017-01-01 10:00:01-08:00   00:00:01        1.0
6760614 2017-01-01 10:00:02-08:00   00:00:01        1.0
6760615 2017-01-01 10:00:03-08:00   00:00:01        1.0
6760616 2017-01-01 10:00:04-08:00   00:00:01        1.0

但是对于像下面这样的其他一些trip_id,您可以观察到我的日期时间差为零(对于两列),而实际上不是。时间差以秒为单位。

df[trip_frame['trip_id'] == '01b8a24510cd4e4684d67b96369286e0'][['datetime','datetime_diff','time_diff']].head(4)

         datetime            datetime_diff  time_diff
3236107 2017-01-28 03:00:00-08:00   0 days  0.0
3236108 2017-01-28 03:00:01-08:00   0 days  0.0
3236109 2017-01-28 03:00:02-08:00   0 days  0.0
3236110 2017-01-28 03:00:03-08:00   0 days  0.0

df[df['trip_id'] == '01c2a70c25e5428bb33811ca5eb19270'][['datetime','datetime_diff','time_diff']].head(4)

        datetime             datetime_diff  time_diff
8915474 2017-01-21 10:00:00-08:00   0 days  0.0
8915475 2017-01-21 10:00:01-08:00   0 days  0.0
8915476 2017-01-21 10:00:02-08:00   0 days  0.0
8915477 2017-01-21 10:00:03-08:00   0 days  0.0

关于实际问题的任何线索?我将不胜感激。

更新 - 我尝试了@n1k31t4 的方法,并为那些有问题的行得到了以下结果。甚至没有做时区转换。它仍然是那么奇怪和令人惊讶。

                        datetime    timestamps    timestamp_diffs    date_diffs
3236107 2017-01-28 11:00:00+00:00   1485601200000000    0.0          0 days
3236108 2017-01-28 11:00:01+00:00   1485601201000000    0.0          0 days
3236109 2017-01-28 11:00:02+00:00   1485601202000000    0.0          0 days
3236110 2017-01-28 11:00:03+00:00   1485601203000000    0.0          0 days
3236111 2017-01-28 11:00:04+00:00   1485601204000000    0.0          0 days
1个回答

很难看出代码的问题所在;鉴于您的评论,我的猜测是时区转换存在问题。

我无法准确看到问题,购买我的建议以帮助调试您的情况是将所有时间转换为时间戳- 默认情况下,自纪元(1970 年 1 月 1 日)以来的秒数。然后这些只是正常值float64(我在下面转换为整数微秒)。如果您的差异仍然返回零,减去简单的数字,那么问题就不会出现在差异上。

这是一个最小的工作示例。一个带有毫秒频率时间戳的简单日期帧:

import pandas as pd
from datetime import datetime

In [1]: df = pd.DataFrame(pd.date_range(start=datetime(2016,1,1,0,0,1), 
    ...:     end=datetime(2016,1,1,0,0,2), freq='ms'), columns=["dates"]).head(10)    # just take first 10 rows for simplicity

创建一个新列,将日期转换为自纪元以来的微秒,作为整数:

In [2]: df["timestamps"] = df.dates.apply(lambda x: int(datetime.timestamp(x) * 1e6))                              

In [3]: df                                                                                                         
Out[3]: 
                    dates        timestamps
0 2016-01-01 00:00:01.000  1451602801000000
1 2016-01-01 00:00:01.001  1451602801001000
2 2016-01-01 00:00:01.002  1451602801002000
3 2016-01-01 00:00:01.003  1451602801003000
4 2016-01-01 00:00:01.004  1451602801004000
5 2016-01-01 00:00:01.005  1451602801005000
6 2016-01-01 00:00:01.006  1451602801006000
7 2016-01-01 00:00:01.007  1451602801007000
8 2016-01-01 00:00:01.008  1451602801008000
9 2016-01-01 00:00:01.009  1451602801009000

此时您可以使用以下方法检查您的任何列中是否没有重复项:

In [4]: df.T.duplicated()                                                                                          
Out[4]: 
dates         False
timestamps    False
dtype: bool

如果有重复,那可能是差异为零的原因。

现在计算差异,在我的例子中是所有 1 毫秒的差异(1000 微秒):

In [5]: df[["date_diffs", "timestamp_diffs"]] = df.diff(1)                                                        

In [6]: df                                                                                                        
Out[6]: 
                    dates        timestamps      date_diffs  timestamp_diffs
0 2016-01-01 00:00:01.000  1451602801000000             NaT              NaN
1 2016-01-01 00:00:01.001  1451602801001000 00:00:00.001000           1000.0
2 2016-01-01 00:00:01.002  1451602801002000 00:00:00.001000           1000.0
3 2016-01-01 00:00:01.003  1451602801003000 00:00:00.001000           1000.0
4 2016-01-01 00:00:01.004  1451602801004000 00:00:00.001000           1000.0
5 2016-01-01 00:00:01.005  1451602801005000 00:00:00.001000           1000.0
6 2016-01-01 00:00:01.006  1451602801006000 00:00:00.001000           1000.0
7 2016-01-01 00:00:01.007  1451602801007000 00:00:00.001000           1000.0
8 2016-01-01 00:00:01.008  1451602801008000 00:00:00.001000           1000.0
9 2016-01-01 00:00:01.009  1451602801009000 00:00:00.001000           1000.0

添加样本零差并检索零差的索引:

In [7]: df.iloc[3, 3] = 0.0                                                                                       

In [8]: np.where(df == 0)                                                                                         
Out[8]: (array([3]), array([3]))

希望这足以找到实际上可能是零差异的地方。如果所有这些都没有零差异,我会查看您的时区转换(也许他们在那里做了一些四舍五入?)或向熊猫问题报告错误


编辑

更新后尝试我的调试方法,并看到这个:

非唯一整数之间的差异永远不会为零

我相信您的系统必须存在错误或固有限制。

熊猫虫

错误可能存在于您特定版本的 Pandas 及其df.diff()方法中。检查您的 Pandas 版本,pd.__version__并查看我上面链接的问题页面以获取任何线索......也许只是尝试最新的稳定版本。

32位系统

另一种可能的解决方案是您在 32 位系统上运行,因此实际上可能会失去我上面示例所需的精度。32 位整数只能保留 10 位的精度。我上面的时间戳需要 12 位数字。您可以在LinuxWindowsMac上找到这样的信息

此外,您可以重试我的示例,但只看seconds而不是microseconds,只是为了确定。