【问题标题】:Holiday Calendar in pandas DataFramepandas DataFrame 中的假日日历
【发布时间】:2018-01-21 02:37:00
【问题描述】:

我为德国创建了一个假期日历(不包括所有日子),如下所示:

from pandas.tseries.holiday import Holiday,AbstractHolidayCalendar

class GermanHolidays(AbstractHolidayCalendar):
    rules = [Holiday('New Years Day', month=1, day=1),
             Holiday('First of May', month=5, day=1),
             Holiday('German Unity Day', month=10,day=3),
            ...]

cal = GermanHolidays()

现在我希望在假期出现或不出现(“1”或“0”)时显示一列。所以我做了以下事情:

holidays = cal.holidays(start=X['Time (CET)'].min(), end = X['Time (CET)'].max())
X['Holidays'] = X['Time (CET)'].isin(holidays)
X['Holidays'] = X['Holidays'].astype(float)

X 是一个数据框,其中Time (CET) 是%d.%m.%Y %H:%M:%S 格式的列。不幸的是,这不起作用。没有引发错误,但所有列都标有"0"。所以没有匹配发生,我真的不知道为什么。 我认为这可能是因为假期的频率是每天而不是每小时,就像在Time (CET) 列中那样。 如果你能帮助我,那就太好了!谢谢!

【问题讨论】:

  • 这可能是因为X['Time (CET)'] 包含日期字符串而不是datetime64s。 X['Time (CET)'].dtype 的值是多少?
  • 感谢您的评论。该列在 dtype datetime64s 中。抱歉没提!

标签: python pandas datetime dataframe calendar


【解决方案1】:

这可能有几个原因。

其中一个as mentioned by @unutbu - is a wrong (string) dtype。确保您的 X['Time (CET)'] 列是 datetime dtype。这可以按如下方式完成:

X['Time (CET)'] = pd.to_datetime(X['Time (CET)'], dayfirst=True, errors='coerce')

你说的另一个原因是时间部分。

这是一个演示:

In [28]: df = pd.DataFrame({'Date':pd.date_range('2017-01-01 01:01:01', 
                                                 freq='9H', periods=1000)})

产量:

In [30]: df
Out[30]:
                   Date
0   2017-01-01 01:01:01
1   2017-01-01 10:01:01
2   2017-01-01 19:01:01
3   2017-01-02 04:01:01
4   2017-01-02 13:01:01
5   2017-01-02 22:01:01
6   2017-01-03 07:01:01
7   2017-01-03 16:01:01
8   2017-01-04 01:01:01
9   2017-01-04 10:01:01
..                  ...
990 2018-01-07 07:01:01
991 2018-01-07 16:01:01
992 2018-01-08 01:01:01
993 2018-01-08 10:01:01
994 2018-01-08 19:01:01
995 2018-01-09 04:01:01
996 2018-01-09 13:01:01
997 2018-01-09 22:01:01
998 2018-01-10 07:01:01
999 2018-01-10 16:01:01

[1000 rows x 1 columns]

holidays 过滤不起作用,因为时间部分不匹配:

In [29]: df.loc[df.Date.isin(holidays)]
Out[29]:
Empty DataFrame
Columns: [Date]
Index: []

我们可以通过规范化(截断时间部分或将时间设置为00:00:00)我们的日期时间列来使其工作:

In [31]: df.loc[df.Date.dt.normalize().isin(holidays)]
Out[31]:
                   Date
0   2017-01-01 01:01:01
1   2017-01-01 10:01:01
2   2017-01-01 19:01:01
320 2017-05-01 01:01:01
321 2017-05-01 10:01:01
322 2017-05-01 19:01:01
734 2017-10-03 07:01:01
735 2017-10-03 16:01:01

【讨论】:

  • 嘿,非常感谢这个工作。不知何故,我遇到了一个问题,即 1 月 1 日我没有得到假期。我认为这是因为我的数据中的一天从凌晨 01:00 开始。我该如何解决这个问题?
  • @inneb,您能否提供一个小的可重现数据集,以便我重现它?
【解决方案2】:

这基本上是你已经拥有的。鉴于这有效而您的无效,这很可能是因为这些值是文本而不是 @unutbu 和 @MaxU 已经指出的时间戳。

另外,您的帖子指出:

在假期出现或不出现时显示(“1”或“0”)

你真的想要一个文本值吗?您尝试转换为浮点数,但您可能只需要整数。

X = pd.DataFrame({'Time (CET)': pd.DatetimeIndex(start='2017-01-01', end='2017-12-31', freq='12H')})
X = X.assign(Holidays=X['Time (CET)'].isin(cal.holidays()).astype(int))
>>> X
             Time (CET)  Holidays
0   2017-01-01 00:00:00         1
1   2017-01-01 12:00:00         0
2   2017-01-02 00:00:00         0
...

【讨论】:

  • 嘿,也非常感谢您的评论。日期时间已转换:)
猜你喜欢
  • 2012-11-07
  • 1970-01-01
  • 2018-04-04
  • 1970-01-01
  • 1970-01-01
  • 2014-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多