与此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)
它可以获得所需的输出,但我想知道numpy
或pandas
中是否有类似于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'
答案 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