Я хочу преобразовать продолжительность в целое число часов (или минут, или секунд). Я думал, что пространство имен .dt
будет работать так же, как и для даты и времени, но вместо этого я получаю ошибку.
Этот пример
from datetime import datetime
import polars as pl
pl.__version__
dx = pl.DataFrame({'dt1': datetime(2024, 1, 12, 13, 45)})
dx.select((pl.col('dt1') - pl.col('dt1').dt.date()).dt.hour())
выдает ошибку:
---------------------------------------------------------------------------
InvalidOperationError Traceback (most recent call last)
Cell In[5], line 2
1 dx = pl.DataFrame({'dt1': datetime(2024, 1, 12, 13, 45)})
----> 2 dx.select((pl.col('dt1') - pl.col('dt1').dt.date()).dt.hour())
File ~/src/poste/sda-poste-logistics/venv/lib/python3.11/site-packages/polars/dataframe/frame.py:8461, in DataFrame.select(self, *exprs, **named_exprs)
8361 def select(
8362 self, *exprs: IntoExpr | Iterable[IntoExpr], **named_exprs: IntoExpr
8363 ) -> DataFrame:
8364 """
8365 Select columns from this DataFrame.
8366
(...)
8459 └───────────┘
8460 """
-> 8461 return self.lazy().select(*exprs, **named_exprs).collect(_eager=True)
File ~/src/poste/sda-poste-logistics/venv/lib/python3.11/site-packages/polars/lazyframe/frame.py:1967, in LazyFrame.collect(self, type_coercion, predicate_pushdown, projection_pushdown, simplify_expression, slice_pushdown, comm_subplan_elim, comm_subexpr_elim, cluster_with_columns, no_optimization, streaming, background, _eager, **_kwargs)
1964 # Only for testing purposes atm.
1965 callback = _kwargs.get("post_opt_callback")
-> 1967 return wrap_df(ldf.collect(callback))
InvalidOperationError: `hour` operation not supported for dtype `duration[μs]`
на обоих полярах 0.20.31 и 1.0.0-а1.
Это баг или я делаю что-то не так?
После вычитания у вас больше нет даты, а есть дельта времени, вы должны использовать dt.total_секунды:
dx.select((pl.col('dt1') - pl.col('dt1').dt.date()).dt.total_seconds())
Выход:
┌───────┐
│ dt1 │
│ --- │
│ i64 │
╞═══════╡
│ 49500 │
└───────┘
Или, как total_hours / дробные часы:
dx.select((pl.col('dt1') - pl.col('dt1').dt.date()).dt.total_hours())
┌─────┐
│ dt1 │
│ --- │
│ i64 │
╞═════╡
│ 13 │
└─────┘
dx.select((pl.col('dt1') - pl.col('dt1').dt.date()).dt.total_seconds()/3600)
┌───────┐
│ dt1 │
│ --- │
│ f64 │
╞═══════╡
│ 13.75 │
└───────┘
Если вам нужно целое число часов в разнице во времени, используйте total_hours()
, а не hour()
. Вызов hour()
предназначен для меток времени.
dx = pl.DataFrame({'dt1': dt.datetime(2024, 1, 12, 13, 45)})
dx.select(
(pl.col('dt1') - pl.col('dt1').dt.date()).dt.total_hours()
)
shape: (1, 1)
┌─────┐
│ dt1 │
│ --- │
│ i64 │
╞═════╡
│ 13 │
└─────┘
Скопировал неправильный кусок кода. Спасибо.
hours
устарел ;)