Идентифицировать непрерывные последовательности или группы логических данных в Pandas

#python #pandas #boolean

#python #pandas #логическое

Вопрос:

У меня есть набор данных, основанный на логическом времени. Согласно приведенному ниже примеру. Я заинтересован в выделении непрерывных последовательностей из более чем трех единиц в наборе данных. Я хотел бы записать это в новом столбце с именем [Continuous_out_x] . Есть ли какая-либо эффективная операция для этого?

Я сгенерировал тестовые данные таким образом:

 df = pd.DataFrame(zip(list(np.random.randint(2, size=20)),list(np.random.randint(2, size=20))), columns=['tag1','tag2'] ,index=pd.date_range('2020-01-01', periods=20, freq='s'))
  

Результат, который я получил, был следующим:

 print (df):
                        tag1  tag2
2020-01-01 00:00:00     0     0
2020-01-01 00:00:01     1     0
2020-01-01 00:00:02     1     0
2020-01-01 00:00:03     1     1
2020-01-01 00:00:04     1     0
2020-01-01 00:00:05     1     0
2020-01-01 00:00:06     1     1
2020-01-01 00:00:07     0     1
2020-01-01 00:00:08     0     0
2020-01-01 00:00:09     1     1
2020-01-01 00:00:10     1     0
2020-01-01 00:00:11     0     1
2020-01-01 00:00:12     1     0
2020-01-01 00:00:13     0     1
2020-01-01 00:00:14     0     1
2020-01-01 00:00:15     0     1
2020-01-01 00:00:16     1     1
2020-01-01 00:00:17     0     0
2020-01-01 00:00:18     0     1
2020-01-01 00:00:19     1     0
  

Решение для этого набора примеров (выше) будет выглядеть следующим образом:

 print(df):
                         tag1  tag2  Continuous_out_1  Continuous_out_2
2020-01-01 00:00:00     0     0                 0                 0
2020-01-01 00:00:01     1     0                 1                 0
2020-01-01 00:00:02     1     0                 1                 0
2020-01-01 00:00:03     1     1                 1                 0
2020-01-01 00:00:04     1     0                 1                 0
2020-01-01 00:00:05     1     0                 1                 0
2020-01-01 00:00:06     1     1                 1                 0
2020-01-01 00:00:07     0     1                 0                 0
2020-01-01 00:00:08     0     0                 0                 0
2020-01-01 00:00:09     1     1                 0                 0
2020-01-01 00:00:10     1     0                 0                 0
2020-01-01 00:00:11     0     1                 0                 0
2020-01-01 00:00:12     1     0                 0                 0
2020-01-01 00:00:13     0     1                 0                 1
2020-01-01 00:00:14     0     1                 0                 1
2020-01-01 00:00:15     0     1                 0                 1
2020-01-01 00:00:16     1     1                 0                 1
2020-01-01 00:00:17     0     0                 0                 0
2020-01-01 00:00:18     0     1                 0                 0
2020-01-01 00:00:19     1     0                 0                 0
  

Ответ №1:

Вы можете сделать это как:

  • создайте серию, которая отличает каждую полосу (группу)
  • назначьте bool группам с более чем тремя строками

код

 # ok to loop over a few columns, still very performant
for col in ["tag1", "tag2"]:
    col_no = col[-1]
    df[f"group_{col}"] = np.cumsum(df[col].shift(1) != df[col])
    df[f"{col}_counts"] = df.groupby(f"group_{col}").tag1.transform("count") > 3
    df[f"Continuous_out_{col_no}"] = df[f"{col}_counts"].astype(int)
    df = df.drop(columns=[f"group_{col}", f"{col}_counts"])
    
  

вывод

                      tag1  tag2  Continuous_out_1  Continuous_out_2
2020-01-01 00:00:00     0     0                 0                 0
           00:00:01     1     0                 1                 0
           00:00:02     1     0                 1                 0
           00:00:03     1     1                 1                 0
           00:00:04     1     0                 1                 0
           00:00:05     1     0                 1                 0
           00:00:06     1     1                 1                 0
           00:00:07     0     1                 0                 0
           00:00:08     0     0                 0                 0
           00:00:09     1     1                 0                 0
           00:00:10     1     0                 0                 0
           00:00:11     0     1                 0                 0
           00:00:12     1     0                 0                 0
           00:00:13     0     1                 0                 1
           00:00:14     0     1                 0                 1
           00:00:15     0     1                 0                 1
           00:00:16     1     1                 0                 1
           00:00:17     0     0                 0                 0
           00:00:18     0     1                 0                 0
           00:00:19     1     0                 0                 0
  

Ответ №2:

Вы можете определить области непрерывных значений True / False и проверить, превышают ли они ваше ограничение.

 for colname, series in df.items():
    new = f'Continuous_{colname}'
    df[new] = series.diff().ne(0).cumsum() # label contiguous regions
    df[new] = series.groupby(df[new]).transform('size') # get size of region
    df[new] = df[new].gt(3) * series # mark with cutoff
  

Вывод

                      tag1  tag2  Continuous_tag1  Continuous_tag2
index
2020-01-01 00:00:00     0     0                0                0
2020-01-01 00:00:01     1     0                1                0
2020-01-01 00:00:02     1     0                1                0
2020-01-01 00:00:03     1     1                1                0
2020-01-01 00:00:04     1     0                1                0
2020-01-01 00:00:05     1     0                1                0
2020-01-01 00:00:06     1     1                1                0
2020-01-01 00:00:07     0     1                0                0
2020-01-01 00:00:08     0     0                0                0
2020-01-01 00:00:09     1     1                0                0
2020-01-01 00:00:10     1     0                0                0
2020-01-01 00:00:11     0     1                0                0
2020-01-01 00:00:12     1     0                0                0
2020-01-01 00:00:13     0     1                0                1
2020-01-01 00:00:14     0     1                0                1
2020-01-01 00:00:15     0     1                0                1
2020-01-01 00:00:16     1     1                0                1
2020-01-01 00:00:17     0     0                0                0
2020-01-01 00:00:18     0     1                0                0
2020-01-01 00:00:19     1     0                0                0
  

Комментарии:

1. хорошее решение 🙂 Я всегда забываю об операторных методах!