1

我想将表达式与 groupby 一起使用,每月进行下采样,因为下采样功能将被弃用。有没有一种简单的方法可以做到这一点, datetime.timedelta 只适用于几天及以下。

4

2 回答 2

2

随着着陆groupby_dynamic,我们现在可以下采样并将整个表达式 API 用于我们的聚合。这意味着我们可以resample通过任何一个。

  • 上采样
  • 下采样
  • 先上采样再下采样

让我们看一个例子:

df = pl.DataFrame(
    {"time": pl.date_range(low=datetime(2021, 12, 16), high=datetime(2021, 12, 16, 3), interval="30m"),
     "groups": ["a", "a", "a", "b", "b", "a", "a"],
     "values": [1., 2., 3., 4., 5., 6., 7.]
    })

print(df)
shape: (7, 3)
┌─────────────────────┬────────┬────────┐
│ time                ┆ groups ┆ values │
│ ---                 ┆ ---    ┆ ---    │
│ datetime            ┆ str    ┆ f64    │
╞═════════════════════╪════════╪════════╡
│ 2021-12-16 00:00:00 ┆ a      ┆ 1      │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2021-12-16 00:30:00 ┆ a      ┆ 2      │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2021-12-16 01:00:00 ┆ a      ┆ 3      │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2021-12-16 01:30:00 ┆ b      ┆ 4      │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2021-12-16 02:00:00 ┆ b      ┆ 5      │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2021-12-16 02:30:00 ┆ a      ┆ 6      │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2021-12-16 03:00:00 ┆ a      ┆ 7      │
└─────────────────────┴────────┴────────┘

上采样

上采样可以通过定义一个区间来完成。这将产生一个DataFrame空值,然后可以用填充策略或插值填充。

df.upsample("time", "15m").fill_null("forward")
shape: (13, 3)
┌─────────────────────┬────────┬────────┐
│ time                ┆ groups ┆ values │
│ ---                 ┆ ---    ┆ ---    │
│ datetime            ┆ str    ┆ f64    │
╞═════════════════════╪════════╪════════╡
│ 2021-12-16 00:00:00 ┆ a      ┆ 1      │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2021-12-16 00:15:00 ┆ a      ┆ 1      │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2021-12-16 00:30:00 ┆ a      ┆ 2      │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2021-12-16 00:45:00 ┆ a      ┆ 2      │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ ...                 ┆ ...    ┆ ...    │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2021-12-16 02:00:00 ┆ b      ┆ 5      │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2021-12-16 02:15:00 ┆ b      ┆ 5      │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2021-12-16 02:30:00 ┆ a      ┆ 6      │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2021-12-16 02:45:00 ┆ a      ┆ 6      │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2021-12-16 03:00:00 ┆ a      ┆ 7      │
└─────────────────────┴────────┴────────┘

(df.upsample("time", "15m")
   .interpolate()
   .fill_null("forward")  # string columns cannot be interpolated
)
shape: (13, 3)
┌─────────────────────┬────────┬────────┐
│ time                ┆ groups ┆ values │
│ ---                 ┆ ---    ┆ ---    │
│ datetime            ┆ str    ┆ f64    │
╞═════════════════════╪════════╪════════╡
│ 2021-12-16 00:00:00 ┆ a      ┆ 1      │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2021-12-16 00:15:00 ┆ a      ┆ 1.5    │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2021-12-16 00:30:00 ┆ a      ┆ 2      │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2021-12-16 00:45:00 ┆ a      ┆ 2      │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ ...                 ┆ ...    ┆ ...    │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2021-12-16 02:00:00 ┆ b      ┆ 5      │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2021-12-16 02:15:00 ┆ b      ┆ 3.5    │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2021-12-16 02:30:00 ┆ a      ┆ 6      │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2021-12-16 02:45:00 ┆ a      ┆ 4      │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2021-12-16 03:00:00 ┆ a      ┆ 7      │
└─────────────────────┴────────┴────────┘

下采样

这是最强大的,因为我们也可以将它与普通的 groupby 键结合起来。在时间序列(按一个或多个键分组)上有一个虚拟移动窗口,可以使用表达式 API 进行聚合。

(df.groupby_dynamic(
    time_column="time", 
    every="1h", 
    closed="both", 
    by="groups", 
    include_boundaries=True
)
    .agg([
        pl.col('time').count(), 
        pl.col("time").max(),
        pl.sum("values"),
    ]))
shape: (4, 7)
┌────────┬────────────┬────────────┬────────────┬────────────┬─────────────────────┬────────────┐
│ groups ┆ _lower_bou ┆ _upper_bou ┆ time       ┆ time_count ┆ time_max            ┆ values_sum │
│ ---    ┆ ndary      ┆ ndary      ┆ ---        ┆ ---        ┆ ---                 ┆ ---        │
│ str    ┆ ---        ┆ ---        ┆ datetime   ┆ u32        ┆ datetime            ┆ f64        │
│        ┆ datetime   ┆ datetime   ┆            ┆            ┆                     ┆            │
╞════════╪════════════╪════════════╪════════════╪════════════╪═════════════════════╪════════════╡
│ a      ┆ 2021-12-16 ┆ 2021-12-16 ┆ 2021-12-16 ┆ 3          ┆ 2021-12-16 01:00:00 ┆ 6          │
│        ┆ 00:00:00   ┆ 01:00:00   ┆ 00:00:00   ┆            ┆                     ┆            │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ a      ┆ 2021-12-16 ┆ 2021-12-16 ┆ 2021-12-16 ┆ 1          ┆ 2021-12-16 00:00:00 ┆ 1          │
│        ┆ 01:00:00   ┆ 02:00:00   ┆ 00:00:00   ┆            ┆                     ┆            │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ a      ┆ 2021-12-16 ┆ 2021-12-16 ┆ 2021-12-16 ┆ 2          ┆ 2021-12-16 03:00:00 ┆ 13         │
│        ┆ 02:00:00   ┆ 03:00:00   ┆ 00:00:00   ┆            ┆                     ┆            │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ b      ┆ 2021-12-16 ┆ 2021-12-16 ┆ 2021-12-16 ┆ 2          ┆ 2021-12-16 02:00:00 ┆ 9          │
│        ┆ 01:00:00   ┆ 02:00:00   ┆ 01:00:00   ┆            ┆                     ┆            │
└────────┴────────────┴────────────┴────────────┴────────────┴─────────────────────┴────────────┘
于 2021-12-18T17:47:09.993 回答
0

我使用圆形表达式和在其后的日期列上的 groupby 操作找到了我的问题的解决方案。

这是一些代码示例:

df = pl.DataFrame(
{
    "A": [
        "2020-01-01",
        "2020-01-02",
        "2020-02-03",
        "2020-02-04",
        "2020-03-05",
        "2020-03-06",
        "2020-06-06",
    ],
    "B": [1.0, 8.0, 6.0, 2.0, 16.0, 10.0,2],
    "C": [3.0, 6.0, 9.0, 2.0, 13.0, 8.0,2],
    "D": [12.0, 5.0, 9.0, 2.0, 11.0, 2.0,2],
}
)
q = (
    df.lazy().with_column(pl.col('A').str.strptime(pl.Date, "%Y-%m-%d").dt.round(rule='month',n=1))
        .groupby('A').agg(
                [pl.col("B").max(),
                pl.col("C").min(),
                 pl.col("D").last()]
            )
        .sort('A')
)
df = q.collect()
print(df)

印刷

┌────────────┬───────┬───────┬────────┐
│ A          ┆ B_max ┆ C_min ┆ D_last │
│ ---        ┆ ---   ┆ ---   ┆ ---    │
│ date       ┆ f64   ┆ f64   ┆ f64    │
╞════════════╪═══════╪═══════╪════════╡
│ 2020-01-01 ┆ 8     ┆ 3     ┆ 5      │
├╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2020-02-01 ┆ 6     ┆ 2     ┆ 2      │
├╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2020-03-01 ┆ 16    ┆ 8     ┆ 2      │
├╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2020-06-01 ┆ 2     ┆ 2     ┆ 2      │
└────────────┴───────┴───────┴────────┘

一些解释,首先我将 String 列转换为 pl.Date 类型,然后使用 .dt 创建日期类型的命名空间。之后,我使用 DateTime 命名空间的 round 函数将每月的所有日期舍入到该月的第一天。结果同一个月的每个日期都得到相同的日期,所以我可以用 groupby 对它们进行分组并在组上使用一些聚合函数。这种方法的缺点(以及下采样)是你错过了不存在日期的月份。为此,你可以使用这段代码,它有点乱,我不得不使用熊猫,但我认为它有效。

from dateutil.relativedelta import relativedelta
date_min = df['A'].dt.min()
date_max = df['A'].dt.max()+relativedelta(months=+1)
t_index=pd.date_range(date_min, date_max, freq='M',closed='right').values
t_index = [datetime.datetime.fromisoformat(str(np.datetime_as_string(x, unit='D'))) for x in t_index]
df_ref = pl.DataFrame(t_index,columns='A')
q=(
    df_ref.lazy().with_column(pl.col('A').cast(pl.Date).dt.round(rule='month',n=1))
    .join(df.lazy(),on='A',how='left')
)
df = q.collect()
print(df)

结果是

┌────────────┬───────┬───────┬────────┐
│ A          ┆ B_max ┆ C_min ┆ D_last │
│ ---        ┆ ---   ┆ ---   ┆ ---    │
│ date       ┆ f64   ┆ f64   ┆ f64    │
╞════════════╪═══════╪═══════╪════════╡
│ 2020-01-01 ┆ 8     ┆ 3     ┆ 5      │
├╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2020-02-01 ┆ 6     ┆ 2     ┆ 2      │
├╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2020-03-01 ┆ 16    ┆ 8     ┆ 2      │
├╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2020-04-01 ┆ null  ┆ null  ┆ null   │
├╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2020-05-01 ┆ null  ┆ null  ┆ null   │
├╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 2020-06-01 ┆ 2     ┆ 2     ┆ 2      │
└────────────┴───────┴───────┴────────┘
于 2021-12-14T11:04:17.010 回答