格式化timedelta64字符串输出

时间:2014-08-15 11:38:01

标签: python numpy pandas timedelta

与此question类似,我在pandas DataFrame中有一个numpy.timedelta64列。根据前面提到的answer问题,有一个函数pandas.tslib.repr_timedelta64可以很好地显示以天,小时:分:秒为单位的timedelta。我想在几天和几小时内格式化它们。

所以我得到的是以下内容:

def silly_format(hours):
    (days, hours) = divmod(hours, 24)
    if days > 0 and hours > 0:
        str_time = "{0:.0f} d, {1:.0f} h".format(days, hours)
    elif days > 0:
        str_time = "{0:.0f} d".format(days)
    else:
        str_time = "{0:.0f} h".format(hours)
    return str_time

df["time"].astype("timedelta64[h]").map(silly_format)

它可以获得所需的输出,但我想知道numpypandas中是否有类似于datetime.strftime的函数可以根据某些格式字符串格式化numpy.timedelta64提供?


我试图进一步调整@ Jeff的解决方案,但它比我的答案要慢。这是:

days = time_delta.astype("timedelta64[D]").astype(int)
hours = time_delta.astype("timedelta64[h]").astype(int) % 24
result = days.astype(str)
mask = (days > 0) & (hours > 0)
result[mask] = days.astype(str) + ' d, ' + hours.astype(str) + ' h'
result[(hours > 0) & ~mask] = hours.astype(str) + ' h'
result[(days > 0) & ~mask] = days.astype(str) + ' d'

4 个答案:

答案 0 :(得分:4)

虽然@sebix和@Jeff提供的答案显示了将timedeltas转换为日期和小时的好方法,并且@ Jeff的解决方案特别保留了Series'索引,但它们缺乏最终格式的灵活性的字符串。我现在使用的解决方案是:

def delta_format(days, hours):
    if days > 0 and hours > 0:
        return "{0:.0f} d, {1:.0f} h".format(days, hours)
    elif days > 0:
        return "{0:.0f} d".format(days)
    else:
        return "{0:.0f} h".format(hours)

days = time_delta.astype("timedelta64[D]")
hours = time_delta.astype("timedelta64[h]") % 24
return [delta_format(d, h) for (d, h) in izip(days, hours)]

非常适合我,我通过将该列表插入原始DataFrame来获取索引。

答案 1 :(得分:1)

以下是如何以矢量化方式进行的操作。

In [28]: s = pd.to_timedelta(range(5),unit='d') + pd.offsets.Hour(3)

In [29]: s
Out[29]: 
0   0 days, 03:00:00
1   1 days, 03:00:00
2   2 days, 03:00:00
3   3 days, 03:00:00
4   4 days, 03:00:00
dtype: timedelta64[ns]

In [30]: days = s.astype('timedelta64[D]').astype(int)

In [31]: hours = s.astype('timedelta64[h]').astype(int)-days*24

In [32]: days
Out[32]: 
0    0
1    1
2    2
3    3
4    4
dtype: int64

In [33]: hours
Out[33]: 
0    3
1    3
2    3
3    3
4    3
dtype: int64

In [34]: days.astype(str) + ' d, ' + hours.astype(str) + ' h'
Out[34]: 
0    0 d, 3 h
1    1 d, 3 h
2    2 d, 3 h
3    3 d, 3 h
4    4 d, 3 h
dtype: object

如果你想完全像OP提出的那样:

In [4]: result = days.astype(str) + ' d, ' + hours.astype(str) + ' h'

In [5]: result[days==0] = hours.astype(str) + ' h'

In [6]: result
Out[6]: 
0         3 h
1    1 d, 3 h
2    2 d, 3 h
3    3 d, 3 h
4    4 d, 3 h
dtype: object

答案 2 :(得分:1)

@Midnighter的答案在Python 3中对我不起作用,所以这是我的更新函数:

def delta_format(delta: np.timedelta64) -> str:
    days = delta.astype("timedelta64[D]") / np.timedelta64(1, 'D')
    hours = int(delta.astype("timedelta64[h]") / np.timedelta64(1, 'h') % 24)

    if days > 0 and hours > 0:
        return f"{days:.0f} d, {hours:.0f} h"
    elif days > 0:
        return f"{days:.0f} d"
    else:
        return f"{hours:.0f} h"

基本相同,但带有f字符串,并且具有更多类型强制性。

答案 3 :(得分:0)

我不知道它是如何在大熊猫中完成的,但这是我对你的问题的唯一解决办法:

import numpy as np
t = np.array([200487900000000,180787000000000,400287000000000,188487000000000], dtype='timedelta64[ns]')

days = t.astype('timedelta64[D]').astype(np.int32) # gives: array([2, 2, 4, 2], dtype=int32)
hours = t.astype('timedelta64[h]').astype(np.int32)%24 # gives: array([ 7,  2, 15,  4], dtype=int32)

所以我只是将原始数据转换为所需的输出类型(让它numpy做),然后我们有两个数据数组,可以随意使用。要成对分组,只需执行:

>>> np.array([days, hours]).T
array([[ 2,  7],
       [ 2,  2],
       [ 4, 15],
       [ 2,  4]], dtype=int32)

例如:

for row in d:
    print('%dd %dh' % tuple(row))

给出:

2d 7h
2d 2h
4d 15h
2d 4h