Кто-нибудь знает, как разобрать неделю YYYY в столбец даты в Polars?
Я пробовал этот код, но он выдает ошибку. Спасибо
import polars as pl
pl.DataFrame(
{
"week": [201901, 201902, 201903, 201942, 201943, 201944]
}).with_columns(pl.col('week').cast(pl.Utf8).str.strptime(pl.Date, fmt='%Y%U').alias("date"))
Этот код работает в Pandas для анализа yyyyww: df['date'] = pd.to_datetime(df.week.astype(str) + '0', format='%Y%W%w')
Это похоже на ошибку (хотя она связана с базовым пакетом ржавчины chrono, а не с самим полярным). Я попытался использовать strptime базового python, и он игнорирует %U
и просто дает первое число года для всех случаев, поэтому вы можете либо выполнять манипуляции со строками, либо математику (при условии, что вам не нужен точный ответ)
pl.DataFrame({
"week": [201901, 201902, 201903, 201942, 201943, 201944]
}) \
.with_columns(pl.col('week').cast(pl.Utf8)) \
.with_columns([pl.col('week').str.slice(0,4).cast(pl.Int32).alias('year'),
pl.col('week').str.slice(4,2).cast(pl.Int32).alias('week')]) \
.select(pl.date(pl.col('year'),1,1) + pl.duration(days=(pl.col('week')-1)*7).alias('date'))
Если вы посмотрите на определение %U, оно должно основываться на х-м воскресенье года, тогда как моя математика просто умножает на 7.
Другой подход состоит в том, чтобы создать df дат, затем сделать из них strftime, а затем присоединиться к dfs. Так что это может быть так:
dfdates=pl.DataFrame({'date':pl.date_range(datetime(2019,1,1), datetime(2019,12,31),'1d').cast(pl.Date())}) \
.with_columns(pl.col('date').dt.strftime("%Y%U").alias('week')) \
.groupby('week').agg(pl.col('date').min())
А затем присоединяясь к тому, что у вас есть
pl.DataFrame({
"week": [201901, 201902, 201903, 201942, 201943, 201944]
}).with_columns(pl.col('week').cast(pl.Utf8())).join(dfdates, on='week')
shape: (6, 2)
┌────────┬────────────┐
│ week ┆ date │
│ --- ┆ --- │
│ str ┆ date │
╞════════╪════════════╡
│ 201903 ┆ 2019-01-20 │
│ 201944 ┆ 2019-11-03 │
│ 201902 ┆ 2019-01-13 │
│ 201943 ┆ 2019-10-27 │
│ 201942 ┆ 2019-10-20 │
│ 201901 ┆ 2019-01-06 │
└────────┴────────────┘
Отлично!!. Спасибо Хотите сообщить о проблеме GH из-за этой ошибки?
Я подозреваю, что это действительно ошибка с базовым пакетом Chrono, поскольку даже базовому python strptime это не нравится.
Но он отлично работает в Pandas для анализа yyyyww: df['date'] = pd.to_datetime(df.week.astype(str) + '0', format='%Y%W%w')
Проблема с этим подходом заключается в том, что я получаю случайный день недели, основанный на 1/1 этого конкретного года. Pandas по умолчанию — воскресенье. Хм
Это просто другой парсер.
Я поднял вопрос GH .
Вы пробовали второй подход?
да, второй подход намного лучше. Спасибо!!
Недельный календарь, используемый для %U, странный. Он возвращает 201900 для 05.01.2019 и 202301 для 07.01.2023, которые являются первыми субботами года. По умолчанию это должно быть воскресенье.
@DeanMacGregor Я не согласен с тем, что это «ошибка», особенно с полярами. Смотрите мой комментарий к проблеме на гитхабе.
@FObersteiner, ну, хронодокумент говорит, что все их спецификаторы работают как при синтаксическом анализе, так и при печати. Если это не работает, то это либо ошибка, либо документ не прав, говоря, что это должно работать. Например, я могу использовать strptime «201901» как %Y%m без указания дня, так почему бы «201901» не работать с %Y%U без указания дня, поскольку спецификации %U таковы, что это воскресенье. Что касается того, что это не ошибка поляров, я уже сказал об этом в своем втором комментарии.
Я согласен, документы могут быть более конкретными, говоря, например, что спецификаторы недели не работают без спецификатора дня недели.
Это действительно странно, приятель, похоже, что нарушены только даты 2019 года, взгляните на мой пример ниже:
pl.DataFrame(
{
"week": [
202201,
202202,
202203,
202242,
202243,
202244,
202101,
202102,
202103,
202142,
202143,
202144,
201901,
201902,
201903,
201942,
201943,
201944,
201801,
201802,
201803,
201842,
201843,
201844,
]
}
).with_columns(pl.format("{}0", "week")).with_columns(
pl.col("week").str.strptime(pl.Date, fmt = "%Y%W%w", strict=False).alias("teste")
)
shape: (24, 2)
┌─────────┬────────────┐
│ week ┆ teste │
│ --- ┆ --- │
│ str ┆ date │
╞═════════╪════════════╡
│ 2022010 ┆ 2022-01-09 │
│ 2022020 ┆ 2022-01-16 │
│ 2022030 ┆ 2022-01-23 │
│ 2022420 ┆ 2022-10-23 │
│ 2022430 ┆ 2022-10-30 │
│ 2022440 ┆ 2022-11-06 │
│ 2021010 ┆ 2021-01-10 │
│ 2021020 ┆ 2021-01-17 │
│ 2021030 ┆ 2021-01-24 │
│ 2021420 ┆ 2021-10-24 │
│ 2021430 ┆ 2021-10-31 │
│ 2021440 ┆ 2021-11-07 │
│ 2019010 ┆ null │
│ 2019020 ┆ null │
│ 2019030 ┆ null │
│ 2019420 ┆ null │
│ 2019430 ┆ null │
│ 2019440 ┆ null │
│ 2018010 ┆ 2018-01-07 │
│ 2018020 ┆ 2018-01-14 │
│ 2018030 ┆ 2018-01-21 │
│ 2018420 ┆ 2018-10-21 │
│ 2018430 ┆ 2018-10-28 │
│ 2018440 ┆ 2018-11-04 │
└─────────┴────────────┘
Помимо ошибки, я всегда использую следующее выражение для анализа количества недель до правильных дат.
.with_columns(pl.format("{}0", "week")).with_columns(pl.col("week").str.strptime(pl.Date, fmt = "%Y%W%w", strict=False)
Важно отметить, что необходимо объединить день недели, чтобы действительно проанализировать этот шаблон, я думаю, что это упоминается в других комментариях к сообщению.
Код отлично работает для YYYYmm, который не является датой. .with_columns([pl.col('месяц').cast(pl.Utf8).str.strptime(pl.Date, fmt='%Y%m').alias("date1")])