【问题标题】:First week of year considering the first day last year考虑到去年的第一天,今年的第一周
【发布时间】:2021-06-02 01:13:45
【问题描述】:

我有以下df:

time_series                  date   sales
store_0090_item_85261507     1/2020   1,0
store_0090_item_85261501     2/2020   0,0
store_0090_item_85261500     3/2020   6,0

“日期”= 周/年。 所以,我尝试使用以下代码:

df['date'] = df['date'].apply(lambda x: datetime.strptime(x + '/0', "%U/%Y/%w"))

但是,返回这个df:

time_series                  date        sales
store_0090_item_85261507     2020-01-05   1,0
store_0090_item_85261501     2020-01-12   0,0
store_0090_item_85261500     2020-01-19   6,0

但是,2020 年第一周的第一天是 2019-12-29,将星期日视为第一天。我怎么能有 2020 年第一周的第一天 2020-12-29 而不是 2020-01-05?

【问题讨论】:

    标签: python pandas datetime


    【解决方案1】:

    来自 datetime 模块的文档:

    %U: 一年中的周数(星期日为一周的第一天),以零填充十进制数表示。新年第一个星期天之前的所有日子都被认为是在第 0 周。

    编辑:我的原始答案不适用于输入 1/2023 并且使用 ISO 8601 date values 不适用于 1/2021,所以我通过添加自定义函数来编辑这个答案

    这是一种使用自定义函数的方式

    import pandas as pd
    from datetime import datetime, timedelta
    ##############################################
    # to demonstrate issues with certain dates
    print(datetime.strptime('0/2020/0', "%U/%Y/%w")) # 2019-12-29 00:00:00
    print(datetime.strptime('1/2020/0', "%U/%Y/%w")) # 2020-01-05 00:00:00
    
    print(datetime.strptime('0/2021/0', "%U/%Y/%w")) # 2020-12-27 00:00:00
    print(datetime.strptime('1/2021/0', "%U/%Y/%w")) # 2021-01-03 00:00:00
    
    print(datetime.strptime('0/2023/0', "%U/%Y/%w")) # 2023-01-01 00:00:00
    print(datetime.strptime('1/2023/0', "%U/%Y/%w")) # 2023-01-01 00:00:00
    #################################################
    
    df = pd.DataFrame({'date':["1/2020", "2/2020", "3/2020", "1/2021", "2/2021", "1/2023", "2/2023"]})
    print(df)
    
    def get_first_day(date):
        date0 = datetime.strptime('0/' + date.split('/')[1] + '/0', "%U/%Y/%w")
        date1 = datetime.strptime('1/' + date.split('/')[1] + '/0', "%U/%Y/%w")
        date = datetime.strptime(date + '/0', "%U/%Y/%w")
        return date if date0 == date1 else date - timedelta(weeks=1)
    
    df['new_date'] = df['date'].apply(lambda x:get_first_day(x))
    print(df)
    
    

    输入

         date
    0  1/2020
    1  2/2020
    2  3/2020
    3  1/2021
    4  2/2021
    5  1/2023
    6  2/2023
    

    输出

         date   new_date
    0  1/2020 2019-12-29
    1  2/2020 2020-01-05
    2  3/2020 2020-01-12
    3  1/2021 2020-12-27
    4  2/2021 2021-01-03
    5  1/2023 2023-01-01
    6  2/2023 2023-01-08
    

    【讨论】:

    • 那需要在解析之前修改输入,不是吗?
    • @MrFuppes 是的,你的答案是更简单的方法
    • 好的,看来 OP 将需要一种或另一种解决方法;两者都不“好”^^顺便说一句。您不必使用lambda,pd.to_datetime 更具可读性和效率。
    • @Vivian Oops 忘记添加那部分了,你需要从 datetime 导入 timedelta,更新了答案
    • 是的,我正在再次运行代码导入 timedelta。
    【解决方案2】:

    你会想要使用ISO weekparsing directives,例如:

    import pandas as pd
    
    date = pd.Series(["1/2020", "2/2020", "3/2020"])
    
    pd.to_datetime(date+"/1", format="%V/%G/%u")
    
    0   2019-12-30
    1   2020-01-06
    2   2020-01-13
    dtype: datetime64[ns]
    

    如果一周应该从星期日开始,您也可以移动一天:

    pd.to_datetime(date+"/1", format="%V/%G/%u") - pd.Timedelta('1d')
     
    0   2019-12-29
    1   2020-01-05
    2   2020-01-12
    dtype: datetime64[ns]
    

    【讨论】:

    • 但是,我希望第一天是星期天,所以我需要 2020-12-29。我可以这样吗?
    • @Vivian:ISO 周从星期一开始,所以你必须解决(见我的编辑)。
    猜你喜欢
    • 2012-06-20
    • 2010-10-24
    • 1970-01-01
    • 1970-01-01
    • 2021-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多