我有两个数据帧中的一些数据,如下所示:

import polars as pl

data = {"channel": [0, 1, 2, 1, 2, 0, 1], "time": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7]}
time_df = pl.DataFrame(data)

data = {
    "time": [10.0, 10.5],
    "event_table": [["start_1", "stop_1", "start_2", "stop_2"], ["start_3"]],
}
events_df = pl.DataFrame(data)

time_df中的channel表示一个新的"事件表"从这里开始.我想分解event_table的每一行,从event_df的通道0开始,得到如下结果:

data = {
    "channel": [1, 2, 1, 2, 1],
    "time": [0.2, 0.3, 0.4, 0.5, 0.7],
    "event": ["start_1", "stop_1", "start_2", "stop_2", "start_3"],
}
result_df = pl.DataFrame(data)

我目前正在做的是从第一个帧中删除所有的通道0,分解第二个数据帧,并使用hstack来组合两个帧.如果我的数据是完美的,这是正常的.

实际上,事件表可以包含更多(或更少)事件.在这些情况下,我想"截断"爆炸(或用空值填充).

import polars as pl

data = {"channel": [0, 1, 2, 1, 2, 0, 1], "time": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7]}
time_df = pl.DataFrame(data)

data = {
    "time": [10.0, 10.5],
    "event_table": [["start_1", "stop_1", "start_2"], ["start_3", "stop_3"]],
}
events_df = pl.DataFrame(data)

data = {
    "channel": [1, 2, 1, 2, 1],
    "time": [0.2, 0.3, 0.4, 0.5, 0.7],
    "event": ["start_1", "stop_1", "start_2", None, "start_3"],
}
result_df = pl.DataFrame(data)

我很感激你的帮助.

推荐答案

我不知道我是否把事情复杂化了,但是:

我们想到的最初方法是对事件进行编号,以便它们与通道中的行索引对齐.

shape: (2, 2)
┌──────────────────────────────────┬───────┐
│ event_table                      ┆ index │
│ ---                              ┆ ---   │
│ list[str]                        ┆ u32   │
╞══════════════════════════════════╪═══════╡ 
│ ["start_1", "stop_1", "start_2"] ┆ 0     │ # [1, 2, 3]
│ ["start_3", "stop_3"]            ┆ 5     │ # [6, 7]
└──────────────────────────────────┴───────┘

我们可以得到每个通道0的行索引:

time_df.with_row_index("zero_index").filter(channel = 0).with_row_index()
shape: (2, 4)
┌───────┬────────────┬─────────┬──────┐
│ index ┆ zero_index ┆ channel ┆ time │
│ ---   ┆ ---        ┆ ---     ┆ ---  │
│ u32   ┆ u32        ┆ i64     ┆ f64  │
╞═══════╪════════════╪═════════╪══════╡
│ 0     ┆ 0          ┆ 0       ┆ 0.1  │
│ 1     ┆ 5          ┆ 0       ┆ 0.6  │
└───────┴────────────┴─────────┴──────┘

其中我们可以.join个go 参加活动.

events_with_id = (
   events_df
    .with_row_index()
    .join(
       time_df.with_row_index("zero_index")
        .filter(channel = 0)
        .with_row_index()
        .select("index", "zero_index"),
       on = "index",
       how = "left"
    )
    .select(
       pl.col("event_table")
         .list.slice(0, pl.col("zero_index").shift(-1) - pl.col("zero_index") - 1)
         .fill_null(pl.col("event_table")),
       index = "zero_index"
    )
    .explode("event_table")
    .with_columns(
       (pl.col("index") + pl.col("index").cum_count()).over("index")
    )
)

.explode()人之后,我们拥有:

shape: (5, 2)
┌─────────────┬───────┐
│ event_table ┆ index │
│ ---         ┆ ---   │
│ str         ┆ u32   │
╞═════════════╪═══════╡
│ start_1     ┆ 0     │
│ stop_1      ┆ 0     │
│ start_2     ┆ 0     │
│ start_3     ┆ 5     │
│ stop_3      ┆ 5     │
└─────────────┴───────┘

.cum_count()的添加给我们:

shape: (5, 2)
┌─────────────┬───────┐
│ event_table ┆ index │
│ ---         ┆ ---   │
│ str         ┆ u32   │
╞═════════════╪═══════╡
│ start_1     ┆ 1     │ # index of 1st channel 0 (plus 1)
│ stop_1      ┆ 2     │
│ start_2     ┆ 3     │
│ start_3     ┆ 6     │ # index of 2nd channel 0 (plus 1)
│ stop_3      ┆ 7     │
└─────────────┴───────┘

然后我们可以对其进行.join,并最终过滤出通道0行.

(time_df
  .with_row_index()
  .join(
     events_with_id,
     on = "index",
     how = "left"
  )
  .filter(pl.col("channel") != 0)
)
shape: (5, 4)
┌───────┬─────────┬──────┬─────────────┐
│ index ┆ channel ┆ time ┆ event_table │
│ ---   ┆ ---     ┆ ---  ┆ ---         │
│ u32   ┆ i64     ┆ f64  ┆ str         │
╞═══════╪═════════╪══════╪═════════════╡
│ 1     ┆ 1       ┆ 0.2  ┆ start_1     │
│ 2     ┆ 2       ┆ 0.3  ┆ stop_1      │
│ 3     ┆ 1       ┆ 0.4  ┆ start_2     │
│ 4     ┆ 2       ┆ 0.5  ┆ null        │
│ 6     ┆ 1       ┆ 0.7  ┆ start_3     │
└───────┴─────────┴──────┴─────────────┘

重叠部分

list.slice()用于截断任何潜在的重叠:

shape: (2, 2)
┌─────────────────────────────────────────────────────────────────┬───────┐
│ event_table                                                     ┆ index │
│ ---                                                             ┆ ---   │
│ list[str]                                                       ┆ u32   │
╞═════════════════════════════════════════════════════════════════╪═══════╡
│ ["start_1", "stop_1", "start_2", "stop_2", "start_3", "stop_3"] ┆ 0     │
│ ["start_4", "stop_4"]                                           ┆ 5     │
└─────────────────────────────────────────────────────────────────┴───────┘
overlap.with_columns(
   pl.col("event_table")
     .list.slice(0, pl.col("index").shift(-1) - pl.col("index") - 1) # truncate
     .fill_null(pl.col("event_table"))                               # refill last row
)
shape: (2, 2)
┌────────────────────────────────────────────┬───────┐
│ event_table                                ┆ index │
│ ---                                        ┆ ---   │
│ list[str]                                  ┆ u32   │
╞════════════════════════════════════════════╪═══════╡
│ ["start_1", "stop_1", "start_2", "stop_2"] ┆ 0     │
│ ["start_4", "stop_4"]                      ┆ 5     │
└────────────────────────────────────────────┴───────┘

Python相关问答推荐

使用GEKKO在简单DTE系统中进行一致初始化

如何在Deliveryter笔记本中从同步上下文正确地安排和等待Delivercio代码中的结果?

为什么默认情况下所有Python类都是可调用的?

如何将多进程池声明为变量并将其导入到另一个Python文件

在极性中创建条件累积和

迭代嵌套字典的值

不能使用Gekko方程'

如何在FastAPI中为我上传的json文件提供索引ID?

CommandeError:模块numba没有属性generated_jit''''

使用特定值作为引用替换数据框行上的值

在Python中调用变量(特别是Tkinter)

python panda ExcelWriter切换动态公式到数组公式

下三角形掩码与seaborn clustermap bug

用SymPy在Python中求解指数函数

不允许 Select 北极滚动?

mdates定位器在图表中显示不存在的时间间隔

如何使用Azure Function将xlsb转换为xlsx?

如何在Python中将超链接添加到PDF中每个页面的顶部?

如何在Python中创建仅包含完整天数的月份的列表

来自任务调度程序的作为系统的Python文件