【问题标题】:Find the end of the month of a Pandas DataFrame Series查找 Pandas DataFrame 系列的月底
【发布时间】:2016-09-18 03:45:43
【问题描述】:

我在 DataFrame 中有一个系列,最初作为对象读取,然后需要将其转换为 yyyy-mm-dd 形式的日期,其中 dd 是月末​​。

例如,我有 DataFrame df,其中包含 Date 列作为对象:

...      Date    ...
...     200104   ...
...     200508   ...

说到这里,我想要的是一个日期对象:

...      Date    ...
...  2001-04-30  ...
...  2005-08-31  ...

这样 df['Date'].item() 返回

datetime.date(2001, 04, 30)

我使用以下代码几乎可以到达那里,但我所有的日期都是在月初,而不是月底。请指教。

df['Date'] = pd.to_datetime(df['Date'], format="%Y%m").dt.date

注意:我已经将 Pandas ad pd 和 datetime 导入为 dt

【问题讨论】:

    标签: python date datetime pandas


    【解决方案1】:

    你可以使用pandas.tseries.offsets.MonthEnd:

    from pandas.tseries.offsets import MonthEnd
    
    df['Date'] = pd.to_datetime(df['Date'], format="%Y%m") + MonthEnd(1)
    

    MonthEnd 中的 1 只是指定向前移动一步到下一个月末日期。 (使用0 或将其留空也适用于您的情况)。如果您想要下个月的最后一天,您可以使用MonthEnd(2) 等。这应该适用于任何月份,因此您不需要知道该月的天数或类似的东西。更多偏移信息可以在documentation找到。

    示例用法和输出:

    df = pd.DataFrame({'Date': [200104, 200508, 201002, 201602, 199912, 200611]})
    df['EndOfMonth'] = pd.to_datetime(df['Date'], format="%Y%m") + MonthEnd(1)
    
         Date EndOfMonth
    0  200104 2001-04-30
    1  200508 2005-08-31
    2  201002 2010-02-28
    3  201602 2016-02-29
    4  199912 1999-12-31
    5  200611 2006-11-30
    

    【讨论】:

    • 这是迄今为止我见过的最优雅的解决方案之一,谢谢! :)
    • 没问题! MonthEnd 是隐藏在 Pandas 中的宝石之一,您不会立即认为 Pandas 会拥有。通常我的第一直觉是使用其他日期时间库..直到我记得 Pandas 有这么酷的功能!
    • 您应该查看@martien lubberink 的回答,了解上述一些注意事项。
    • 这似乎不适用于 pandas 0.19.2 和 numpy 1.13.1。收到错误“数据类型日期时间不理解”。有人遇到过这个问题吗?
    • answer by Martein 中所述,对于一个月的最后一个日期,MonthEnd(1) 的使用是不正确的,而应始终只使用MonthEnd(0)
    【解决方案2】:

    同意 root 提供是正确的方法。然而,盲目使用MonthEnd(1) 的读者如果使用当月的最后一个日期作为输入,他们会大吃一惊:

    In [4]: pd.Timestamp('2014-01-01') + MonthEnd(1)
    Out[4]: Timestamp('2014-01-31 00:00:00')
    
    In [5]: pd.Timestamp('2014-01-31') + MonthEnd(1)
    Out[5]: Timestamp('2014-02-28 00:00:00')
    

    使用MonthEnd(0) 会给出这样的结果:

    In [7]: pd.Timestamp('2014-01-01') + MonthEnd(0)
    Out[7]: Timestamp('2014-01-31 00:00:00')
    
    In [8]: pd.Timestamp('2014-01-31') + MonthEnd(0)
    Out[8]: Timestamp('2014-01-31 00:00:00')
    

    以字符串形式获取月末的示例:

    from pandas.tseries.offsets import MonthEnd
    (pd.Timestamp.now() + MonthEnd(0)).strftime('%Y-%m-%dT00:00:00')
    # '2014-01-31T00:00:00'
    

    【讨论】:

      【解决方案3】:

      月末可以是该月的最后一天/分钟/秒/毫秒/微秒/纳秒,具体取决于您的用例所需的offset。给定日期,要导出月份的最后一个单位,请使用适用的anchored offset semantics。例如:

      import pandas as pd
      
      def last_second_of_month(date: str) -> str:
          return str(pd.Timestamp(date) + pd.offsets.MonthBegin() - pd.offsets.Second())
      

      根据需要,将上面的Second() 替换为Day()Minute()Milli()Micro()Nano()

      这是一个具有相同结果的替代实现:

      import pandas as pd
      
      def last_second_of_month(date: str) -> str:
          return str((pd.Timestamp(date) + pd.offsets.MonthEnd(0)).date()) + " 23:59:59"
      

      例子:

      >>> last_second_of_month('2020-10')
      '2020-10-31 23:59:59'
      >>> last_second_of_month('2020-10-01')
      '2020-10-31 23:59:59'
      >>> last_second_of_month('2020-10-15')
      '2020-10-31 23:59:59'
      >>> last_second_of_month('2020-10-30')
      '2020-10-31 23:59:59'
      >>> last_second_of_month('2020-10-31')
      '2020-10-31 23:59:59'
      

      作为警告,请勿使用 pd.Timestamp(date) + pd.offsets.MonthEnd() + pd.offsets.Day() - pd.offsets.Second(),因为它在一个月的最后一天无法正常工作。关于pd.offsets.MonthEnd(1) 的这一观察归功于answer by Martien

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-11-22
        • 1970-01-01
        • 2016-10-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-11
        相关资源
        最近更新 更多