【问题标题】:Converting Pandas column from days to days, hours, minutes将 Pandas 列从天转换为天、小时、分钟
【发布时间】:2021-02-04 04:00:02
【问题描述】:

我正在尝试转换列df["time_ro_reply"] 它仅包含十进制的天数到包含天数、小时数、分钟数的 timedelta 格式。这使它更具人类可读性。

我正在阅读有关 pd.to_timedelta 的信息,但我正在努力实现它: pd.to_timedelta(df["time_to_reply"]) 这只返回 0。

示例输入:

df["time_ro_reply"]
1.881551
0.903264
2.931560
2.931560

预期输出:

df["time_ro_reply"]
1 days 19 hours 4 minutes
0 days 23 hours 2 minutes
2 days 2 hours 23 minutes
2 days 2 hours 23 minutes

【问题讨论】:

  • 如果您可以将示例输入与预期输出共享,那就太好了。
  • @MayankPorwal 感谢您的反馈,我已经更新了问题。实际上我的输入是十进制格式的天数(例如 3.23 天...)
  • 我找到了一个解决方案,但我虽然已经有一个编码函数:def days_hours_minutes(td): return td.days, td.seconds//3600, (td.seconds//60)%60
  • 我不确定是否有专门用于此的编码函数。必须为它做数学,就像你做的那样。

标签: python pandas timedelta


【解决方案1】:

我建议使用如下自定义函数:

import numpy as np
import pandas as pd

# creating the provided dataframe
df = pd.DataFrame([1.881551, 0.903264, 2.931560, 2.931560],
                   columns = ["time_ro_reply"])

# this function converts a time as a decimal of days into the desired format
def convert_time(time):

    # calculate the days and remaining time
    days, remaining = divmod(time, 1)

    # calculate the hours and remaining time
    hours, remaining = divmod(remaining * 24, 1)

    # calculate the minutes
    minutes = divmod(remaining * 60, 1)[0]

    # a list of the strings, rounding the time values
    strings = [str(round(days)), 'days',
               str(round(hours)), 'hours',
               str(round(minutes)), 'minutes']

    # return the strings concatenated to a single string
    return ' '.join(strings)

# add a new column to the dataframe by applying the function
# to all values of the column 'time_ro_reply' using .apply()
df["desired_output"] = df["time_ro_reply"].apply(lambda t: convert_time(t))

这会产生以下数据框:

    time_ro_reply   desired_output
0   1.881551        1 days 21 hours 9 minutes
1   0.903264        0 days 21 hours 40 minutes
2   2.931560        2 days 22 hours 21 minutes
3   2.931560        2 days 22 hours 21 minutes

但是,这会产生与您描述的不同的输出。如果 'time_ro_reply' 值确实被解释为纯小数,我看不出你是如何得到预期结果的。您介意分享一下您是如何获得它们的吗?

我希望 cmets 能很好地解释代码。如果不是,并且您不熟悉诸如 e.g. 之类的语法。 divmod()、apply(),我建议在 Python / Pandas 文档中查找它们。

如果这有帮助,请告诉我。

【讨论】:

    【解决方案2】:

    使用 MrB here 展示的 nice 函数的修改版本,

    def display_time(seconds, granularity=2):
        intervals = (('days', 86400),
                     ('hours', 3600),
                     ('minutes', 60),
                     ('seconds', 1),
                     ('microseconds', 1e-6))
        result = []
        for name, count in intervals:
            value = seconds // count
            if value:
                seconds -= value * count
                name = name.rstrip('s') if value == 1 else name
                result.append(f"{int(value)} {name}")
            else:
                result.append(f"{0} {name}")
        return ', '.join(result[:granularity])
    

    如果您将“time_to_reply”列转换为秒并应用该函数,您也可以获得所需的输出:

    import pandas as pd
    
    df = pd.DataFrame({"time_to_reply": [1.881551, 0.903264, 2.931560, 2.931560]})
    df['td_str'] = df['time_to_reply'].apply(lambda t: display_time(t*24*60*60, 3))
    # df['td_str']
    # 0      1 day, 21 hours, 9 minutes
    # 1    0 days, 21 hours, 40 minutes
    # 2    2 days, 22 hours, 21 minutes
    # 3    2 days, 22 hours, 21 minutes
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-01
      • 1970-01-01
      • 2011-02-14
      • 1970-01-01
      • 2011-01-08
      • 1970-01-01
      • 2019-02-22
      相关资源
      最近更新 更多