Рассмотрим пример кода Polars:
df.with_columns(
pl.date_ranges(
pl.col("current_start"), pl.col("current_end"), "1mo", closed = "left"
).alias("current_tpoints")
).drop("current_start", "current_end").with_columns(
pl.date_ranges(
pl.col("history_start"), pl.col("history_end"), "1mo", closed = "left"
).alias("history_tpoints")
).drop(
"history_start", "history_end"
)
Ключевой проблемой, на которую следует обратить внимание, является повторяемость history_*
и current_*
. Я мог бы уменьшить дублирование, выполнив следующее:
for x in ["history", "current"]:
fstring = f"{x}" + "_{other}"
start = fstring.format(other = "start")
end = fstring.format(other = "end")
df = df.with_columns(
pl.date_ranges(
pl.col(start),
pl.col(end),
"1mo",
closed = "left",
).alias(fstring.format(other = "tpoints"))
).drop(start, end)
Но есть ли другие способы уменьшить дублирование, которые мне следует рассмотреть?
Поскольку кажется, что вам не нужны исходные столбцы, вы можете использовать select() вместо with_columns(), так что drop()
столбцы вам не нужны.
И вы можете перебирать имена столбцов внутри select()
/with_columns()
:
df.select(
pl.date_ranges(
pl.col(f"{c}_start"), pl.col(f"{c}_end"), "1mo", closed = "left"
).alias(f"{c}_tpoints") for c in ["current", "history"]
)
Чтобы объяснить, почему это работает:
Согласно документации, оба метода select()
и with_columns()
могут *exprs: IntoExpr | Iterable[IntoExpr]
, что означает переменное количество аргументов. Видите ли, это может быть либо несколько выражений, либо несколько списков выражений.
Это именно то, что мы можем сделать с помощью понимания списка, мы просто создаем список выражений.
[
pl.date_ranges(
pl.col(f"{c}_start"), pl.col(f"{c}_end"), "1mo", closed = "left"
).alias(f"{c}_tpoints") for c in ["current", "history"]
]
[<Expr ['col("current_start").date_rang…'] at 0x206D93030E0>,
<Expr ['col("history_start").date_rang…'] at 0x206D8F85520>]
Который мы затем можем передать в полярный метод. Обратите внимание, что в окончательном ответе у меня не было квадратных скобок. Это потому, что нам на самом деле не нужен список выражений, нам просто нужен итерируемый объект (в данном случае — генератор).
Я добавил несколько комментариев, надеюсь, это поможет. По сути, мы используем понимание списка Python для создания списка выражений, который затем передаем в метод поляров.
Ой! Можете ли вы указать мне какую-нибудь документацию о том, почему выражение цикла работает? Интерпретируется ли это как выражение на стороне Python (например, аналогично тому, что происходит в
map_elements
, или оно интерпретируется как выражение на стороне Polars/Rust?