使用多个数据帧的pandas时间偏移

2024-06-26 14:52:29 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两个pandas数据帧:

一个名为sdtarray的浮点(代表秒):

    z1  z2  z3  ...
0   NaN NaN NaN
1   2.6 3.4 63.0
2   NaN NaN NaN
3   0.1 1.1 60.7
4   4.7 5.2 64.9
5   0.1 0.6 61.1
...
[33945 rows x 95 columns]

还有一个格式化的日期(newtime):

^{pr2}$

在float DataFrame(sdtarray)中,用相应的日期(相同的行索引,但是newtime数据帧)偏移每一行的最佳方法是什么?以日期的数据帧结尾?在

输出示例如下:

    z4                  z5                  z6              …
0   NaN                 NaN                 NaN 
1   01/09/2014 05:38:02 01/09/2014 05:38:03 01/09/2014 05:39:03 
2   NaN                 NaN                 NaN 
3   01/09/2014 06:27:00 01/09/2014 06:27:01 01/09/2014 06:28:00 
4   01/09/2014 06:37:04 01/09/2014 06:37:05 01/09/2014 06:38:04 
5   01/09/2014 06:57:00 01/09/2014 06:57:00 01/09/2014 06:58:01
…               

我使用的是pandas 0.13.1,我知道它没有什么帮助,但我还是坚持这个,因为它必须与nump1.7.1兼容,这是因为ArcGIS的要求。在

我设法在每一行上使用itertuples得到正确的输出(并使用timedelta,但是对于大数据(34k行乘以100col)来说速度非常慢,而且必须有一种更有效的方法,不依赖于在循环中检查每个rol/列。在

如有任何帮助和指导,我们将不胜感激:)


Tags: columns数据方法pandas代表nanfloatrows
3条回答

在0.17.0中,有一种方法比我的评论中的答案更简单、更简单:

In [81]:
def func(x):
    z1 = pd.NaT
    z2 = pd.NaT
    z3 = pd.NaT
    if pd.notnull(x['z1']):
        z1 = dt.timedelta(seconds =x['z1'])
    if pd.notnull(x['z2']):
        z2 = dt.timedelta(seconds =x['z2'])
    if pd.notnull(x['z3']):
        z3 = dt.timedelta(seconds =x['z3'])
    return pd.Series([z1,z2,z3])
date.values + sdtarray.apply(lambda row: func(row), axis=1) 

Out[81]:
                        0                       1                       2
0                     NaT                     NaT                     NaT
1 2014-09-01 05:38:02.600 2014-09-01 05:38:03.400 2014-09-01 05:39:03.000
2                     NaT                     NaT                     NaT
3 2014-09-01 06:27:00.100 2014-09-01 06:27:01.100 2014-09-01 06:28:00.700
4 2014-09-01 06:37:04.700 2014-09-01 06:37:05.200 2014-09-01 06:38:04.900
5 2014-09-01 06:57:00.100 2014-09-01 06:57:00.600 2014-09-01 06:58:01.100

在下面,我首先检查了seconds(df1)不是NaN之后,将其转换为datetime.timedelta对象,然后将这些值添加到df2中的日期。在

在熊猫0.13.1下测试。在

import datetime as dt
import pandas as pd

df1 = pd.DataFrame({'z1': [None, 2.6, None, 0.1, 4.7, 0.1], 
                    'z2': [None, 3.4, None, 1.1, 5.2, 0.6], 
                    'z3': [None, 63, None, 60.7, 64.9, 61.1]})
df2 = pd.DataFrame({'Datetime': ['2014-09-01 05:22', '2014-09-01 05:38', '2014-09-01 06:08', 
                                 '2014-09-01 06:27', '2014-09-01 06:37', '2014-09-01 06:57']})
df2['Datetime'] = pd.to_datetime(df2.Datetime)

result = df1.applymap(lambda x: dt.timedelta(seconds=x) if not np.isnan(x) else None) 
         + np.tile(df2.values, (1, df1.shape[1]))

>>> pd.DataFrame(result)
                          z1                         z2                         z3
0                        NaT                        NaT                        NaT
1 2014-09-01 05:38:02.600000 2014-09-01 05:38:03.400000        2014-09-01 05:39:03
2                        NaT                        NaT                        NaT
3 2014-09-01 06:27:00.100000 2014-09-01 06:27:01.100000 2014-09-01 06:28:00.700000
4 2014-09-01 06:37:04.700000 2014-09-01 06:37:05.200000 2014-09-01 06:38:04.900000
5 2014-09-01 06:57:00.100000 2014-09-01 06:57:00.600000 2014-09-01 06:58:01.100000

编辑:

对于完全矢量化的解决方案,可以通过以下方式将秒转换为timedelta对象

seconds_td = (1e9*seconds.fillna(0)).astype('timedelta64')

乘以1e9可转换为纳秒。我们填充空值,否则类型转换将失败。在

你能做的

^{pr2}$

注意这里的计算是在底层数组上进行的。这是因为在处理Pandas对象时由于某些错误或其他原因而导致广播失败。 列名将丢失,但您可以轻松地将它们放回:

result.columns = seconds.columns

它不是最干净的,但它应该比使用.applymap快几个数量级。你可以在新版熊猫中做得更干净。以下是一些10万行的基准测试:

^{4}$

相关问题 更多 >