【问题标题】:Convert timestamps in seconds to hh:mm:ss time以秒为单位的时间戳转换为 hh:mm:ss 时间
【发布时间】:2018-11-29 01:57:39
【问题描述】:

我有一个 df 和一个 column 以秒为单位显示时间。我想将它们转换为hh:mmhh:mm:ss

如果时间超过标准的 24 小时时间,我仍然希望它位于 hh:mm:ss。不是'n' days hh:mm:ss

举个例子:

import pandas as pd
import numpy as np
import datetime

ts1 = ['21000', np.nan, '40000', np.nan, '49000', '100000']
ts2 = [0, 2, 'yy', 3, 'yy', 'yy']
ts3 = [0, 2, np.nan, 3, 4, np.nan]
d =  {'X': ts1, 'Y': ts2, 'Z': ts3}
df = pd.DataFrame(data=d)

输出:

        X   Y    Z
0   21000   0  0.0
1     NaN   2  2.0
2   40000  yy  NaN
3     NaN   3  3.0
4   49000  yy  4.0
5  100000  yy  NaN

我可以在单个 string 上使用:

t = str(datetime.timedelta(seconds=21000))

输出时间:

5:50:00    

但是我如何将相同的函数传递给一整列呢?

#t_col = str(datetime.timedelta(seconds=df['ts1']))

预期输出:

          X   Y    Z
0   5:50:00   0  0.0
1       NaN   2  2.0
2  11:06:40  yy  NaN
3       Nan   3  3.0
4  13:36:40  yy  4.0
5  27:46:40  yy  NaN

【问题讨论】:

    标签: python pandas time timedelta


    【解决方案1】:

    使用pandas.to_timedelta 后跟一些杂乱的字符串格式将天数转换为小时数:

    def formatter(x):
        x = str(x)
        return str(int(x[-8:-6])+int(x.split('days')[0])*24).zfill(2) + x[-6:]
    
    df['TD'] = pd.to_timedelta(df['X'].fillna(0).astype(int), unit='s')\
                 .apply(formatter)
    
    print(df)
    
            X   Y    Z        TD
    0   21000   0  0.0  05:50:00
    1     NaN   2  2.0  00:00:00
    2   40000  yy  NaN  11:06:40
    3     NaN   3  3.0  00:00:00
    4   49000  yy  4.0  13:36:40
    5  100000  yy  NaN  27:46:40
    

    【讨论】:

    • 效果很好@jpp
    【解决方案2】:

    更循序渐进的方法

    首先,让我们创建新列并摆脱讨厌的NaN

    In [156]: df['new_column'] = df.X.fillna(0)
    
    In [157]: df
    Out[157]:
           X   Y    Z new_column
    0  21000   0  0.0      21000
    1    NaN   2  2.0          0
    2  40000  yy  NaN      40000
    3    NaN   3  3.0          0
    4  49000  yy  4.0      49000
    5  80000  yy  NaN      80000
    

    然后我们可以根据您编写的代码使用lambda 函数来处理创建增量。请注意,对于timedeltaseconds 参数,我们必须将新列的值转换为ints。

    In [158]: df['new_column'] = df.apply(lambda x: datetime.timedelta(seconds=int(x['new_column'])), axis=1)
    
    In [159]: df
    Out[159]:
           X   Y    Z new_column
    0  21000   0  0.0   05:50:00
    1    NaN   2  2.0   00:00:00
    2  40000  yy  NaN   11:06:40
    3    NaN   3  3.0   00:00:00
    4  49000  yy  4.0   13:36:40
    5  80000  yy  NaN   22:13:20
    

    使用单线

    在我们之前写的基础上,我们需要去掉NaNs,然后把整个系列先转换成ints,再转换成timedeltas。

    In [173]: df['td'] = pd.to_timedelta(pd.to_numeric(df.X.fillna(0)), unit='s')
    
    In [174]: df
    Out[174]:
           X   Y    Z new_column       td
    0  21000   0  0.0   05:50:00 05:50:00
    1    NaN   2  2.0   00:00:00 00:00:00
    2  40000  yy  NaN   11:06:40 11:06:40
    3    NaN   3  3.0   00:00:00 00:00:00
    4  49000  yy  4.0   13:36:40 13:36:40
    5  80000  yy  NaN   22:13:20 22:13:20
    

    这种方法应该更快,因为 apply 相当 slow

    根据您的评论,为了与NaNs保持一致,您可以使用这个

    df['td'] = df.apply(lambda x: x['td'] if x['X'] is not np.NaN else None, axis=1)
    

    【讨论】:

    • 另外,我们可以在转换之前或之后删除 00:00:00 吗?
    • @PeterJames123,您正在重新定义问题。这超出了您最初询问的范围
    • 不是吗? NaN的很好。现在我需要删除那些。如果时间实际上是 00:00:00 怎么办。我将无法区分。
    • 我指的是您删除的评论,您要求我在超过 24 小时的时间内编写代码。你的第一个问题在范围内,我已经更新了我的回答来回答它
    • 噢,对不起。我可以添加这些。都好。我会做一个 .replace
    猜你喜欢
    • 2015-06-17
    • 1970-01-01
    • 1970-01-01
    • 2012-02-10
    • 2017-05-28
    • 1970-01-01
    • 1970-01-01
    • 2015-04-29
    • 2021-03-15
    相关资源
    最近更新 更多