Как отформатировать объект timedelta [duplicate]

Вы можете настроить параметры печати pandas с помощью set_printoptions.

In [3]: df.describe()
Out[3]: 

Index: 8 entries, count to max
Data columns:
x1    8  non-null values
x2    8  non-null values
x3    8  non-null values
x4    8  non-null values
x5    8  non-null values
x6    8  non-null values
x7    8  non-null values
dtypes: float64(7)

In [4]: pd.set_printoptions(precision=2)

In [5]: df.describe()
Out[5]: 
            x1       x2       x3       x4       x5       x6       x7
count      8.0      8.0      8.0      8.0      8.0      8.0      8.0
mean   69024.5  69025.5  69026.5  69027.5  69028.5  69029.5  69030.5
std       17.1     17.1     17.1     17.1     17.1     17.1     17.1
min    69000.0  69001.0  69002.0  69003.0  69004.0  69005.0  69006.0
25%    69012.2  69013.2  69014.2  69015.2  69016.2  69017.2  69018.2
50%    69024.5  69025.5  69026.5  69027.5  69028.5  69029.5  69030.5
75%    69036.8  69037.8  69038.8  69039.8  69040.8  69041.8  69042.8
max    69049.0  69050.0  69051.0  69052.0  69053.0  69054.0  69055.0

Однако это не будет работать во всех случаях, поскольку pandas обнаруживает вашу ширину консоли и будет использовать только to_string, если выход подходит в консоли (см. docstring set_printoptions). В этом случае вы можете явно называть to_string, как указано в BrenBarn .

Обновить

С версией 0.10 печатаются широкоформатные кадры данных :

In [3]: df.describe()
Out[3]: 
                 x1            x2            x3            x4            x5  \
count      8.000000      8.000000      8.000000      8.000000      8.000000   
mean   59832.361578  27356.711336  49317.281222  51214.837838  51254.839690   
std    22600.723536  26867.192716  28071.737509  21012.422793  33831.515761   
min    31906.695474   1648.359160     56.378115  16278.322271     43.745574   
25%    45264.625201  12799.540572  41429.628749  40374.273582  29789.643875   
50%    56340.214856  18666.456293  51995.661512  54894.562656  47667.684422   
75%    75587.003417  31375.610322  61069.190523  67811.893435  76014.884048   
max    98136.474782  84544.484627  91743.983895  75154.587156  99012.695717   

                 x6            x7  
count      8.000000      8.000000  
mean   41863.000717  33950.235126  
std    38709.468281  29075.745673  
min     3590.990740   1833.464154  
25%    15145.759625   6879.523949  
50%    22139.243042  33706.029946  
75%    72038.983496  51449.893980  
max    98601.190488  83309.051963  

Кроме того, изменился API для настройки параметров панды:

In [4]: pd.set_option('display.precision', 2)

In [5]: df.describe()
Out[5]: 
            x1       x2       x3       x4       x5       x6       x7
count      8.0      8.0      8.0      8.0      8.0      8.0      8.0
mean   59832.4  27356.7  49317.3  51214.8  51254.8  41863.0  33950.2
std    22600.7  26867.2  28071.7  21012.4  33831.5  38709.5  29075.7
min    31906.7   1648.4     56.4  16278.3     43.7   3591.0   1833.5
25%    45264.6  12799.5  41429.6  40374.3  29789.6  15145.8   6879.5
50%    56340.2  18666.5  51995.7  54894.6  47667.7  22139.2  33706.0
75%    75587.0  31375.6  61069.2  67811.9  76014.9  72039.0  51449.9
max    98136.5  84544.5  91744.0  75154.6  99012.7  98601.2  83309.1

23
задан Rishav Sharan 18 January 2012 в 10:19
поделиться

7 ответов

, но мне было интересно, могу ли я сделать это в одной строке, используя любую функцию времени времени, такую ​​как strftime.

Насколько я могу судить, нет встроенный метод timedelta, который делает это. Если вы делаете это часто, вы можете создать свою собственную функцию, например

def strfdelta(tdelta, fmt):
    d = {"days": tdelta.days}
    d["hours"], rem = divmod(tdelta.seconds, 3600)
    d["minutes"], d["seconds"] = divmod(rem, 60)
    return fmt.format(**d)

Использование:

>>> print strfdelta(delta_obj, "{days} days {hours}:{minutes}:{seconds}")
1 days 20:18:12
>>> print strfdelta(delta_obj, "{hours} hours and {minutes} to go")
20 hours and 18 to go

Если вы хотите использовать строковый формат ближе к одному используется strftime, мы можем использовать string.Template .

from string import Template

class DeltaTemplate(Template):
    delimiter = "%"

def strfdelta(tdelta, fmt):
    d = {"D": tdelta.days}
    d["H"], rem = divmod(tdelta.seconds, 3600)
    d["M"], d["S"] = divmod(rem, 60)
    t = DeltaTemplate(fmt)
    return t.substitute(**d)

Использование:

>>> print strfdelta(delta_obj, "%D days %H:%M:%S")
1 days 20:18:12
>>> print strfdelta(delta_obj, "%H hours and %M to go")
20 hours and 18 to go

totalSeconds value is показанный как 13374 вместо 99774. т.е. игнорируя значение «day».

Обратите внимание, что в примере выше вы можете использовать timedelta.days для получения значения «день».

В качестве альтернативы, из Python 2.7, timedelta имеет метод total_seconds () , который возвращает общее количество секунд, содержащихся в длительности.

40
ответ дан Shawn Chin 5 September 2018 в 11:29
поделиться

Небольшой вариант на Shawn Chin 's answer - который также обращается к последующей проблеме , поднятой mpouncett - прокладывает часы, минуты и секунды с ведущими нулями, чтобы гарантировать, что все 3 элемента используют 2 места (более соответствуют спецификации этих полей в strftime ):

from string import Template

class DeltaTemplate(Template):
    delimiter = "%"

def strfdelta(tdelta, fmt):
    d = {"D": tdelta.days}
    hours, rem = divmod(tdelta.seconds, 3600)
    minutes, seconds = divmod(rem, 60)
    d["H"] = '{:02d}'.format(hours)
    d["M"] = '{:02d}'.format(minutes)
    d["S"] = '{:02d}'.format(seconds)
    t = DeltaTemplate(fmt)
    return t.substitute(**d)

Вот тест для некоторых значений выборки:

from datetime import timedelta
for seconds in [0, 1, 59, 60, 61, 3599, 3600, 3601]:
    print strfdelta(timedelta(0, seconds), '%H:%M:%S')

И вот вывод:

00:00:00
00:00:01
00:00:59
00:01:00
00:01:01
00:59:59
01:00:00
01:00:01
7
ответ дан Community 5 September 2018 в 11:29
поделиться

Вы можете использовать модуль dateutil, который имеет более дружественный объект relativedelta.

import dateutil
import datetime

alpha = datetime.datetime(2012, 1, 16, 6, 0)
beta = datetime.datetime(2012, 1, 18, 10, 42, 57, 230301)
delta = dateutil.relativedelta(beta, alpha)

это дает вам дельта объекта, который выглядит как

>>> delta
relativedelta(days=+2, hours=+4, minutes=+42, seconds=+57, microseconds=+230301)

. Затем вы можете сделать

print('turnaround %i hrs %i mins %i secs' % (delta.days * 24 + delta.hours, delta.minutes, delta.seconds)

)

5
ответ дан dabhaid 5 September 2018 в 11:29
поделиться
def to_time(seconds):
  delta = datetime.timedelta(seconds=seconds)
  return str(delta.days) + 'd ' + (datetime.datetime.utcfromtimestamp(0) + datetime.timedelta(seconds=delta.seconds)).strftime('%H:%M')
2
ответ дан Daniel F 5 September 2018 в 11:29
поделиться

Вышеупомянутые ответы, похоже, не обрабатывают значения negative timedelta (как получено, например, pytz для часовых поясов «слева» от UTC). Как для документации , объекты timedelta нормализованы, а отрицательный timedelta представлен отрицательным атрибутом экземпляра day. Из документации:

Обратите внимание, что сначала нормализация отрицательных значений может быть неожиданным.

и что

Строковые представления объектов timedelta нормированы аналогично их внутреннему представлению. Это приводит к несколько необычным результатам для отрицательных timedeltas.

Например:

>>> td = timedelta(seconds=-30)
>>> str(td)
'-1 day, 23:59:30'
>>> repr(td)
'datetime.timedelta(-1, 86370)'

Учитывая этот пример timedelta, принятый ответ Shawn Chin и ответ return '23:59:30' и mpounsett '-1:59:30'.

Я думаю, чтобы напечатать как отрицательные, так и положительные timedeltas в более читаемым образом, мы должны явно обрабатывать знак и абсолютное значение объекта часового пояса:

def strfdelta(td, fmt):

    # Get the timedelta’s sign and absolute number of seconds.
    sign = "-" if td.days < 0 else "+"
    secs = abs(td).total_seconds()

    # Break the seconds into more readable quantities.
    days, rem = divmod(secs, 86400)  # seconds per day: 24 * 60 * 60
    hours, rem = divmod(rem, 3600)  # seconds per hour: 60 * 60
    mins, secs = divmod(rem, 60)

    # Format (as per above answers) and return the result string.
    t = DeltaTemplate(fmt)
    return t.substitute(
        s=sign,
        D="{:d}".format(int(days)),
        H="{:02d}".format(int(hours)),
        M="{:02d}".format(int(mins)),
        S="{:02d}".format(int(secs)),
        )

Эта функция возвращает более читаемое строковое представление:

>>> strfdelta(td, "%s%H:%M:%S")  # Note that %s refers to the timedelta’s sign.
'-00:00:30'
>>> strfdelta(timedelta(days=-1), "%s%D %H:%M:%S")
'-1 00:00:00'
>>> strfdelta(timedelta(days=-1, minutes=5), "%s%D %H:%M:%S")
'-0 23:55:00'
>>> strfdelta(timedelta(days=-1, minutes=-5), "%s%D %H:%M:%S")
'-1 00:05:00'

... или в более практическом контексте часовых поясов:

>>> import pytz
>>> import datetime
>>> td = pytz.timezone("Canada/Newfoundland").utcoffset(datetime.datetime.now())
>>> td
datetime.timedelta(-1, 77400)
>>> strfdelta(td, fmt="%s%H:%M")
'-02:30'
>>> td = pytz.timezone("Australia/Eucla").utcoffset(datetime.datetime.now())
>>> td
datetime.timedelta(0, 31500)
>>> strfdelta(td, fmt="%s%H:%M")
'+08:45'
1
ответ дан Jens 5 September 2018 в 11:29
поделиться

Ответ Shawn Chin - хороший, но одна проблема заключается в том, что если вы пропустите определенный элемент в своем формате (как в его втором примере, который имеет только часы и минуты, а не дни или секунды), тогда это время исчезает от вашего результата. Вы можете изменить его, чтобы исправить эту проблему и получить более точные результаты, обработав только те ключевые слова, которые действительно отображаются в строке формата.

class DeltaTemplate(Template):
    delimiter = '%'

def strfdelta(tdelta, fmt):
    d = {}
    l = {'D': 86400, 'H': 3600, 'M': 60, 'S': 1}
    rem = int(tdelta.total_seconds())

    for k in ( 'D', 'H', 'M', 'S' ):
        if "%{}".format(k) in fmt:
            d[k], rem = divmod(rem, l[k])

    t = DeltaTemplate(fmt)
    return t.substitute(**d)

Использование:

>>> print strfdelta(delta_obj, "%D days %H:%M:%S")
1 days 20:18:12
>>> print strfdelta(delta_obj, "%H hours and %M to go")
44 hours and 18 to go

Это негибкий о форматировании, так как вы не можете применять строки преобразования и завершаться такими уродливыми вещами, как это:

>>> delta_obj = timedelta(minutes=5, seconds=2)
>>> print strfdelta(delta_obj, "%H:%M:%S")
0:5:2

Однако вы можете применить тот же подход и применить его к string.Formatter вместо строки .Template и получить что-то гораздо лучше.

from string import Formatter

def strfdelta(tdelta, fmt):
    f = Formatter()
    d = {}
    l = {'D': 86400, 'H': 3600, 'M': 60, 'S': 1}
    k = map( lambda x: x[1], list(f.parse(fmt)))
    rem = int(tdelta.total_seconds())

    for i in ('D', 'H', 'M', 'S'):
        if i in k and i in l.keys():
            d[i], rem = divmod(rem, l[i])

    return f.format(fmt, **d)

Использование:

>>> delta_obj = timedelta(days=1, hours=20, minutes=18, seconds=12)
>>> print strfdelta(delta_obj, "{D} days {H}:{M}:{S}")
1 days 20:18:12
>>> print strfdelta(delta_obj, "{H} hours and {M} to go") 
44 hours and 18 to go

>>> delta_obj = timedelta(minutes=5, seconds=2)                     
>>> print strfdelta(delta_obj, "{H:02}h{M:02}m{S:02}s")  
00h05m02s
>>> print strfdelta(delta_obj, "{H:02}:{M:02}:{S:02}")
00:05:02
11
ответ дан mpounsett 5 September 2018 в 11:29
поделиться

В Python2.7 или новее вы можете использовать метод total_seconds :

import datetime as dt

turnaround = dt.timedelta(days = 1, hours = 3, minutes = 42, seconds = 54)

total_seconds = int(turnaround.total_seconds())
hours, remainder = divmod(total_seconds,60*60)
minutes, seconds = divmod(remainder,60)

print('{} hrs {} mins {} secs'.format(hours,minutes,seconds))

дает

27 hrs 42 mins 54 secs

В Python2.6 или вы можете сами вычислить total_seconds:

total_seconds = turnaround.seconds + turnaround.days*24*60*60

(для более общей формулы, включая микросекунды, см. ссылку выше).

13
ответ дан unutbu 5 September 2018 в 11:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: