【问题标题】:Create new column with categorical variables based on date range使用基于日期范围的分类变量创建新列
【发布时间】:2020-05-30 10:00:48
【问题描述】:

如果我有这样的数据,其中包含一年(2019 年)的日期时间序列日期 -

datetime
0   15.02.19 13:00
1   15.02.19 14:00
2   15.02.19 15:00
3   15.02.19 16:00
4   15.02.19 17:00

如果我的日期时间在一个范围内(学校假期日期从 2019 年开始)和“学期时间”,我想创建一个新列,其值为“学校假期”,否则我将如何以最有效的方式处理此问题?生成的数据框应如下所示-

datetime    school holiday
0   15.02.19 13:00  Term time
1   15.02.19 14:00  Term time
2   15.02.19 15:00  Term time
3   15.02.19 16:00  Term time
4   15.02.19 17:00  School Holiday

我的想法是我会参加学校假期日期,这将是这样的:

Autumn Half Term Holidays   21 Oct 2019 - 25 Oct 2019
Winter Holidays             23 Dec 2019 - 3 Jan 2020
etc...

并用这些日期制作字典,然后以某种方式使用lamba apply?本质上,函数应该是 - if datetime == holiday_range: 'school holiday' else: 'Term time'。

感谢您的帮助

【问题讨论】:

    标签: python pandas datetime time-series


    【解决方案1】:

    也许这会有所帮助:

    holidays = {'Autumn Half Term Holidays': ('16 Feb 2019', '25 Feb 2019')}
    holidays_map = {date.date(): holiday for holiday, dates in holidays.items() for date in pd.date_range(*dates)}
    
    df['holiday'] = df['datetime'].dt.date.map(holidays_map).fillna('Term time')
    
    df
    
                 datetime                    holiday
    0 2019-02-15 13:00:00                  Term time
    1 2019-02-15 14:00:00                  Term time
    2 2019-02-15 15:00:00                  Term time
    3 2019-02-15 16:00:00                  Term time
    4 2019-02-16 17:00:00  Autumn Half Term Holidays
    

    【讨论】:

    • 哦,这很聪明(而且非常有效),因为假期可能没有时间部分:D +1
    • @ALollz 我将如何构建字典,以便不是将每个日期范围映射到像“秋季半学期假期”这样的独特假期,而是将我所有的假期映射到一个类别,即。 '学校假期' ?谢谢
    【解决方案2】:

    您的 DataFrame 中的行数可能比唯一的 Holidays 多。对于这样的问题,您可能需要在某个地方循环,所以最好在较少的假期中循环

    将您的日期转换为 datetime dtype,让我们将假期存储在单独的 DataFrame 中,再次使用 datetime dtype

    import pandas as pd
    df['datetime'] = pd.to_datetime(df['datetime'], format='%d.%m.%y %H:%M')
    
    df2 = pd.DataFrame({'Holiday': ['Autumn Half Term Holidays', 'Winter Holidays'],
                        'start': pd.to_datetime(['2019-10-21', '2019-12-23']),
                        'end': pd.to_datetime(['2019-10-25', '2020-01-03'])})
    

    现在要确定某事是否是假期,我们检查日期时间是否在 任何 个期间之间。地图只会获取您的标签,而不是 True/False。考虑到您的假期,我在您的示例中添加了一行,只是为了说明它有效。

    df['holiday'] = (pd.concat([df['datetime'].between(start, end) for start,end in zip(df2.start, df2.end)], 1)
                       .any(1)
                       .map({True: 'School Holiday', False: 'Term time'}))
    
                 datetime         holiday
    0 2020-01-01 01:00:00  School Holiday
    1 2019-02-15 13:00:00       Term time
    2 2019-02-15 14:00:00       Term time
    3 2019-02-15 15:00:00       Term time
    4 2019-02-15 16:00:00       Term time
    5 2019-02-15 17:00:00       Term time
    

    【讨论】:

    • 谢谢!虽然我觉得对于大型数据集 zipa 的解决方案可能会更快,但这非常有效?
    • @ojp 是的,解决方案会很快。只要假期不是太多,这不会太糟糕。尽管如果您的假期(或时间跨度)的时间分量类似于“2019-12-01 14:00:00 - 2019-12-23 16:45:00”,则很难概括该解决方案。仍然总是最好使用解决问题的最佳方法,即 zipa 的 :D
    • 史诗,我会把你的解决方案放在口袋里,等到那个问题出现时!
    猜你喜欢
    • 1970-01-01
    • 2012-09-15
    • 1970-01-01
    • 2020-10-10
    • 1970-01-01
    • 2013-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多