Подсчитывать последовательные истинные (или 1) значения в логическом (или числовом) столбце с полярами?

Я надеюсь подсчитать последовательные значения в столбце, предпочтительно используя выражения Polars.

import polars
df = pl.DataFrame(
   {"values": [True,True,True,False,False,True,False,False,True,True]}
)

В приведенном выше примере фрейма данных я хотел бы подсчитать количество последовательных значений True.

Ниже приведен пример вывода с использованием пакета R Data.Table.

library(data.table)
dt <- data.table(value = c(T,T,T,F,F,T,F,F,T,T))
dt[, value2 := fifelse((1:.N) == .N & value == 1, .N, NA_integer_), by = rleid(value)]
dt
ценить значение2 истинный нет данных истинный нет данных истинный 3 ЛОЖЬ нет данных ЛОЖЬ нет данных истинный 1 ЛОЖЬ нет данных ЛОЖЬ нет данных истинный нет данных истинный 2

Любые идеи, кто это мог бы сделать эффективно, используя Polars?

[EDIT с новым подходом]

Я получил его работу с кодом ниже, но надеюсь, что есть более эффективный способ. Кто-нибудь знает имена полей структуры/словаря по умолчанию из value_counts?

(
    df.lazy()
    .with_row_count()
    .with_column(
        pl.when(pl.col("value") == False).then(
            pl.col("row_nr")
            
        ).fill_null(
            strategy = "forward"
        ).alias("id_consecutive_Trues")
    )
    .with_column(
        pl.col("id_consecutive_Trues").value_counts(sort = True)
    )
    .with_column(
        (
            pl.col("id_consecutive_Trues").arr.eval(
                pl.element().struct().rename_fields(["value", "count"]).struct.field("count")
            ).arr.max()
            - pl.lit(1)
        ).alias("max_consecutive_true_values")
    )
    .collect()
)

Имена полей .value_counts — это название того, что вы считаете, а counts так что id_consecutive_Trues и counts в данном случае.

jqurious 10.02.2023 00:07
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
81
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это можно рассматривать как групповую операцию.

Обычный способ генерировать идентификаторы групп для последовательных значений — проверить != .shift() и использовать .cumsum()

Здесь я выделил каждый шаг отдельно .with_columns(), но его можно упростить:

(
   df
   .with_columns(
      (pl.col("values") != pl.col("values").shift(+1))
      .alias("change"))
   .with_columns(
      pl.col("change").cumsum()
        .alias("group"))
   .with_columns(
      pl.count().over("group"))
   .with_columns(
      (pl.col("values") != pl.col("values").shift(-1))
      .alias("keep"))
   .with_columns(                        
      pl.when(pl.col("values") & pl.col("keep"))
        .then(pl.col("count"))
        .alias("values2"))
)

shape: (10, 6)
┌────────┬────────┬───────┬───────┬───────┬─────────┐
│ values | change | group | count | keep  | values2 │
│ ---    | ---    | ---   | ---   | ---   | ---     │
│ bool   | bool   | u32   | u32   | bool  | u32     │
╞════════╪════════╪═══════╪═══════╪═══════╪═════════╡
│ true   | true   | 1     | 3     | false | null    │
│ true   | false  | 1     | 3     | false | null    │
│ true   | false  | 1     | 3     | true  | 3       │
│ false  | true   | 2     | 2     | false | null    │
│ false  | false  | 2     | 2     | true  | null    │
│ true   | true   | 3     | 1     | true  | 1       │
│ false  | true   | 4     | 2     | false | null    │
│ false  | false  | 4     | 2     | true  | null    │
│ true   | true   | 5     | 2     | false | null    │
│ true   | false  | 5     | 2     | true  | 2       │
└────────┴────────┴───────┴───────┴───────┴─────────┘

Один из возможных способов написать это «менее подробным» образом:

df.with_columns(
   pl.when(
      pl.col("values") &
      pl.col("values").shift_and_fill(-1, False).is_not())
   .then(
      pl.count().over(
         (pl.col("values") != pl.col("values").shift())
         .cumsum()))
)

shape: (10, 2)
┌────────┬───────┐
│ values | count │
│ ---    | ---   │
│ bool   | u32   │
╞════════╪═══════╡
│ true   | null  │
│ true   | null  │
│ true   | 3     │
│ false  | null  │
│ false  | null  │
│ true   | 1     │
│ false  | null  │
│ false  | null  │
│ true   | null  │
│ true   | 2     │
└────────┴───────┘

Спасибо! Я думал использовать смену, но понял, что это будет слишком дорого. Любое понимание того, будет ли ваше решение более эффективным, чем подход? Я буду сравнивать оба. Еще раз спасибо за быстрый ответ!

JGrant06 11.02.2023 19:11

Я бы подумал, что он более эффективен, поскольку, кажется, выполняет меньше работы, чем ваш пример, но я могу ошибаться. Если вы используете .arr.eval, вы можете попробовать добавить parallel=True, чтобы увидеть, влияет ли это на ваш тест.

jqurious 11.02.2023 19:15

Другие вопросы по теме