Рассмотрим следующий фрейм данных.
df = pl.DataFrame(data = {"col1": range(10)})
┌──────┐
│ col1 │
│ --- │
│ i64 │
╞══════╡
│ 0 │
│ 1 │
│ 2 │
│ 3 │
│ 4 │
│ 5 │
│ 6 │
│ 7 │
│ 8 │
│ 9 │
└──────┘
Допустим, у меня есть список кортежей, где первое значение представляет начальный индекс, а второе значение — значение длины (как используется в pl.DataFrame.slice
). Это может выглядеть так:
slices = [(1,2), (5,3)]
Теперь, каков хороший способ разрезать/извлечь два фрагмента из df
, при этом первый фрагмент начинается в строке 1 и имеет длину 2, а второй фрагмент начинается в строке 5 и имеет длину 3.
Вот что я ищу:
┌──────┐
│ col1 │
│ --- │
│ i64 │
╞══════╡
│ 1 │
│ 2 │
│ 5 │
│ 6 │
│ 7 │
└──────┘
Вы можете использовать pl.DataFrame.slice для получения каждого среза отдельно, а затем использовать pl.concat для объединения всех срезов.
pl.concat(df.slice(*slice) for slice in slices)
shape: (5, 1)
┌──────┐
│ col1 │
│ --- │
│ i64 │
╞══════╡
│ 1 │
│ 2 │
│ 5 │
│ 6 │
│ 7 │
└──────┘
Редактировать. В качестве попытки векторизованного подхода вы можете сначала использовать список параметров среза для создания кадра данных индексов (используя pl.int_ranges
и pl.DataFrame.explode
). После этого этот фрейм данных индексов можно использовать для нарезки df
с помощью соединения.
indices = (
pl.DataFrame(slices, orient = "row", schema=["offset", "length"])
.select(
index=pl.int_ranges("offset", pl.col("offset") + pl.col("length"))
)
.explode("index")
)
shape: (5, 1)
┌───────┐
│ index │
│ --- │
│ i64 │
╞═══════╡
│ 1 │
│ 2 │
│ 5 │
│ 6 │
│ 7 │
└───────┘
(
indices
.join(
df,
left_on = "index",
right_on=pl.int_range(pl.len()),
how = "left",
coalesce=True,
)
.drop("index")
)
shape: (5, 1)
┌──────┐
│ col1 │
│ --- │
│ i64 │
╞══════╡
│ 1 │
│ 2 │
│ 5 │
│ 6 │
│ 7 │
└──────┘
@Andi Я добавил попытку векторизованного решения в своем последнем редактировании. Однако я не уверен на 100%, позволяет ли это избежать цикла по списку параметров среза (поскольку его необходимо проанализировать при создании кадра данных indices
). Мне было бы интересно узнать, приведет ли это к увеличению производительности ваших данных.
Однострочник выглядит гораздо лаконичнее ;-) В любом случае, спасибо, что показали альтернативу.
Это работает. Однако мне интересно, существует ли векторизованное решение? Могу ли я избежать цикла for?