python:根据条件对时间序列数据进行分组或拆分

问题描述 投票:2回答:1

我在工作中处理大量时间序列数据,并且一直在尝试使用python(尤其是pandas)来使某些工作更快一些。我有一些代码可以读取DataFrame中的数据,并标识满足指定条件的段。然后,将这些段分成单独的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用户。

这是它的作用:我或多或少地基于一组条件创建了一个遮罩,并获取了该遮罩中所有True值的索引位置。然后,它使用NumPy的.diff()函数来识别索引中的不连续性。在for循环内,它在每个识别出的不连续位置处将蒙版拆分。完成此操作后,我可以使用现在分开的索引集从原始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, :]

[df1df2包含原始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开头可以更干净,更有效地完成同样的事情。

itertools或pandas的groupby可以做到这一点吗?我还没有找到一种方法使之工作。

python pandas time-series pandas-groupby itertools
1个回答
0
投票

欢迎使用堆栈溢出。

我认为您的代码可以这样简化:

# Get the subset that fulfills your conditions

df_conditioned = df.query('Temp > 23 and Temp < 30').copy()
# Check for discontinuities by looking at the indices
# I created a new column called 'Group' to keep track of the continuous indices

indices = df_conditioned.index.to_series()
df_conditioned['Group'] = ((indices - indices.shift(1)) != 1).cumsum()
# Store the groups (segments with same group number) as individual frames in a list

df_list = []
for group in df_conditioned['Group'].unique():
    df_list.append(df_conditioned.query('Group == @group').drop(columns='Group'))

希望有帮助!

© www.soinside.com 2019 - 2024. All rights reserved.