Как добавить скользящие ключевые показатели эффективности в исходный фрейм данных в полярах? когда я группирую, я не вижу индекса и поэтому не могу присоединиться? Я хочу сохранить все исходные столбцы в фрейме данных нетронутыми, но добавить в фрейм данных скользящий KPI?
Код Панды:
groups_df = df[mask_for_filter].groupby(['group_identifier'])
rolling_kpi = groups_df[['col_1', 'col_2']].rolling(15, min_periods=1, center=True).median().reset_index(level='group_identifier').sort_index()
df.loc[mask_for_filter, 'col_1_median'] = rolling_kpi['col_1']
df.loc[mask_for_filter, 'col_2_median'] = rolling_kpi['col_2']
Поляры:
df = df.filter(mask_for_filter).group_by('group_identifier').agg(
col_1_median=pl.col('col_1').rolling_median(15, min_periods=1, center=True),
col_2_median=pl.col('col_2').rolling_median(15, min_periods=1, center=True))
Код: result_df должен быть таким же, как df, за исключением того, что с дополнительными скользящими медианными столбцами, чего не происходит выше... плюс нет индекса, поэтому невозможно объединить/объединить
import polars as pl
import numpy as np
np.random.seed(0)
data = {
'group_identifier': np.random.choice(['A', 'B', 'C'], 100),
'col_1': np.random.randn(100).round(2),
'col_2': np.random.randn(100).round(2),
'other_col': np.random.randn(100).round(2)
}
df = pl.DataFrame(data)
mask_for_filter = df['col_1'] > 0
result_df = df.filter(mask_for_filter).group_by('group_identifier').agg(
col_1_median=pl.col('col_1').rolling_median(15, min_periods=1, center=True),
col_2_median=pl.col('col_2').rolling_median(15, min_periods=1, center=True)
)
mask_for_avg
нигде не определяется.
Хотите ли вы, чтобы в результате были те же строки, что и df
или result_df
. В первом случае: какую скользящую медиану следует назначить строкам в df
с pl.col(col_1) <= 0
.
Похоже, вам не нужно группировать, а вместо этого запустить rolling_median() над окном.
group_identifier
.Если вам нужны только отфильтрованные строки:
(
df
.filter(mask_for_filter)
.with_columns(
pl.col("col_1", "col_2")
.rolling_median(15, min_periods=1, center=True)
.over("group_identifier")
.name.suffix("_median")
)
)
┌──────────────────┬───────┬───────┬───────────┬──────────────┬──────────────┐
│ group_identifier ┆ col_1 ┆ col_2 ┆ other_col ┆ col_1_median ┆ col_2_median │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ str ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │
╞══════════════════╪═══════╪═══════╪═══════════╪══════════════╪══════════════╡
│ B ┆ 0.01 ┆ 1.68 ┆ 1.12 ┆ 0.83 ┆ -0.46 │
│ B ┆ 0.37 ┆ -0.26 ┆ 0.04 ┆ 0.85 ┆ -0.66 │
│ A ┆ 0.72 ┆ -0.38 ┆ 0.47 ┆ 0.93 ┆ -0.44 │
│ A ┆ 0.36 ┆ -0.51 ┆ -0.4 ┆ 0.86 ┆ -0.5 │
...
└──────────────────┴───────┴───────┴───────────┴──────────────┴──────────────┘
Или, если вам это нужно в исходном DataFrame
col_1 > 0
, и второй, чтобы не включать строки, которые будут фильтроваться при вычислении скользящей медианы.(
df
.with_columns(
pl.when(pl.col("col_1") > 0).then(
pl.when(pl.col("col_1") > 0).then(pl.col("col_1", "col_2"))
.rolling_median(15, min_periods=1, center=True)
.over("group_identifier")
)
.name.suffix("_median")
)
)
Если вы хотите добавить больше агрегатов, вы можете обобщить их (хотя я не уверен, что они достаточно читаемы, чтобы перейти к производству):
(
df
.with_columns(
pl.when(pl.col("col_1") > 0).then(
transform(
pl.when(pl.col("col_1") > 0).then(pl.col("col_1", "col_2")),
15, min_periods=1, center=True
)
.over("group_identifier")
)
.name.suffix(suffix)
for transform, suffix in [
(pl.Expr.rolling_median, "_median"),
(pl.Expr.rolling_mean, "_mean"),
]
)
)
Очень круто, я думаю, что последующие действия не подходят, но спрошу, хочу ли я использовать скользящее среднее, а также скользящую медиану, имеет ли смысл повторять приведенный выше блок со средним значением или есть более чистый способ сделать это над самим собой?
Я добавил возможность к ответу
Добавьте к вопросу примеры данных и ожидаемый результат. См. stackoverflow.com/help/minimal-reproducible-example.