Я много работаю с данными временных рядов на своей работе, и я пытался использовать python - в частности pandas - чтобы сделать некоторые работы немного быстрее. У меня есть некоторый код, который считывает данные в DataFrame
и идентифицирует сегменты, где выполняются указанные условия. Затем он разделяет эти сегменты на отдельные кадры данных.
У меня есть образец DataFrame
здесь:
Date Time Pressure Temp Flow Valve Position
0 3/5/2020 12:00:01 5.32 22.12 199 1.00
1 3/5/2020 12:00:02 5.36 22.25 115 0.95
2 3/5/2020 12:00:03 5.33 22.18 109 0.92
3 3/5/2020 12:00:04 5.38 23.51 103 0.90
4 3/5/2020 12:00:05 5.42 24.27 99 0.89
5 3/5/2020 12:00:06 5.49 25.91 92 0.85
6 3/5/2020 12:00:07 5.55 26.78 85 0.82
7 3/5/2020 12:00:08 5.61 29.88 82 0.76
8 3/5/2020 12:00:09 5.69 31.16 87 0.79
9 3/5/2020 12:00:10 5.72 32.01 97 0.87
10 3/5/2020 12:00:11 5.59 29.68 104 0.90
11 3/5/2020 12:00:12 5.53 24.55 111 0.93
12 3/5/2020 12:00:13 5.48 23.54 116 0.96
13 3/5/2020 12:00:14 5.44 23.11 119 1.00
14 3/5/2020 12:00:15 5.41 23.08 121 1.00
Код, который я написал, делает то, что я хочу, но действительно трудно следовать, и я уверен, что это оскорбительно для опытных python users.
Вот что он делает: я более или менее создаю маску на основе набора условий и беру позиции индекса для всех значений True
в маске. Затем он использует функцию NumPy .diff()
, чтобы определить разрыв в индексах. Внутри for
l oop он разделяет маску в месте каждого определенного разрыва. Как только это будет завершено, я могу использовать теперь отдельные наборы индексов, чтобы вырезать нужные сегменты данных из моего исходного DataFrame
. См. Код ниже:
import pandas as pd
import numpy as np
df = pd.read_csv('sample_data.csv')
idx = np.where((df['Temp'] > 23) & (df['Temp'] < 30))[0]
discontinuity = np.where(np.diff(idx) > 1)[0]
intervals = {}
for i in range(len(discontinuity)+1):
if i == 0:
intervals[i] = df.iloc[idx[0]:idx[discontinuity[i]],1]
if len(intervals[i].values) < 1:
del intervals[i]
elif i == len(discontinuity):
intervals[i] = df.iloc[idx[discontinuity[i-1]+1]:idx[-1],1]
if len(intervals[i].values) < 1:
del intervals[i]
else:
intervals[i] = df.iloc[idx[discontinuity[i-1]+1]:idx[discontinuity[i]],1]
if len(intervals[i].values) < 1:
del intervals[i]
df1 = df.loc[intervals[0].index, :]
df2 = df.loc[intervals[1].index, :]
df1
и df2
содержат все данные в оригинале DataFrame
, соответствующие временам (строкам), в которых 'Temp'
находится между 23 и 30.
df1
:
Date Time Pressure Temp Flow Valve Position
3 3/5/2020 12:00:04 5.38 23.51 103 0.90
4 3/5/2020 12:00:05 5.42 24.27 99 0.89
5 3/5/2020 12:00:06 5.49 25.91 92 0.85
6 3/5/2020 12:00:07 5.55 26.78 85 0.82
df2
:
Date Time Pressure Temp Flow Valve Position
10 3/5/2020 12:00:11 5.59 29.68 104 0.90
11 3/5/2020 12:00:12 5.53 24.55 111 0.93
12 3/5/2020 12:00:13 5.48 23.54 116 0.96
13 3/5/2020 12:00:14 5.44 23.11 119 1.00
Я рад, что смог заставить это работать для меня, и я могу жить с парой линии, которые теряются при использовании этого метода, но я знаю, что это действительно пешеходный подход, и я не могу не думать, что кто-то, кто не является python, может сделать то же самое намного более чисто и эффективно.
Может ли groupby
из itertools или pandas работать на это? Я не смог найти способ заставить эту работу.