如何在包含有关两行的信息的同时对数据框进行分组?

时间:2016-08-28 12:56:58

标签: python pandas dataframe timestamp pandas-groupby

我是Python的新手,我希望有人可以帮助我解决这个性能问题。 我的数据如下:

                   TIMESTAMP   A
34   2050-09-08 03:00:00 EST   3.0
40   2050-09-08 07:00:00 EST   3.0
67   2050-09-08 17:00:00 EST   6.0
84   2050-09-08 23:00:00 EST   6.0
89   2050-09-09 01:00:00 EST  11.0
103  2050-09-09 07:00:00 EST  10.0
110  2050-09-09 11:00:00 EST  10.0
118  2050-09-09 15:00:00 EST  10.0

我希望获得A列中的值为Steady(S),Increase(I)或Decreasing(D)的时间间隔。

此时,我使用for循环比较行并计算这些值之间的斜率。只要斜率的符号在每次迭代中都不会改变,则更新间隔的结束时间戳。这导致像Interval(开始,结束,状态)这样的间隔。上面例子的结果是:

Interval(2050-09-08 03:00:00 EST, 2050-09-08 07:00:00 EST, S)
Interval(2050-09-08 07:00:00 EST, 2050-09-08 17:00:00 EST, I)
Interval(2050-09-08 17:00:00 EST, 2050-09-08 23:00:00 EST, S)
etc.

由于数据集包含许多行和列,我试图找到一种更有效地编码的方法(没有for循环)。

data['slope'] = compute_slopes(data)
data['state'].apply(lambda x: get_state(x))
data["shift"] = data["state"].shift(1)
data["check"] = data["state"] != data["shift"]
data["group"] = data["check"].cumsum()
begin_group = data.groupby("group").first()
end_group = data.groupby("group").last()
result = pd.concat([begin_group, end_group])
result = result.sort_values('TIMESTAMP')

                def compute_slopes(data):
                    next_df = data.shift(-1)
                    return getSlope(pd.to_datetime(df['TIMESTAMP'], format = '%Y-%m-%d %H:%M:%S EST'), df['A'], pd.to_datetime(next_df['TIMESTAMP'], format = '%Y-%m-%d %H:%M:%S EST'), next_df['A'])


                def get_slope(x1, y1, x2, y2):
                    return (y2 - y1) / ((x2 - x1).dt.total_seconds()/60)


                def get_state(slope):
                    if(slope < 0):
                        state = 'D'     #DECREASING
                    elif(slope == 0):
                        state = 'S'     #STEADY
                    else:
                        state = 'I'     #INCREASING

                    return state

上面的代码结果如下所示,但是对这个数据框进行分组不起作用,因为有一个状态属于两个时间戳(状态S属于03:00:00和07:00:00)。

     TIMESTAMP                  A     slope     state
34   2050-09-08 03:00:00 EST   3.0  0.000000     S
40   2050-09-08 07:00:00 EST   3.0  0.005000     I
67   2050-09-08 17:00:00 EST   6.0  0.000000     S
84   2050-09-08 23:00:00 EST   6.0  0.041667     I
89   2050-09-09 01:00:00 EST  11.0 -0.002778     D
103  2050-09-09 07:00:00 EST  10.0  0.000000     S
110  2050-09-09 11:00:00 EST  10.0  0.000000     S
118  2050-09-09 15:00:00 EST  10.0  0.000000     S

在某种程度上,我想对这些状态进行分组,并获取每个状态的开始和结束时间戳,并将其保存在一个间隔中。有没有人知道比循环数据框更快的方法?

1 个答案:

答案 0 :(得分:0)

这应该会有所帮助。使用大量shift,然后使用groupby + agg

df.loc[df.A < df.A.shift(-1), 'State'] = 'I'
df.loc[df.A > df.A.shift(-1), 'State'] = 'D'
df.loc[df.A == df.A.shift(-1).ffill(), 'State'] = 'S'
df['StateGroup'] = (df.State != df.State.shift()).cumsum()
df['NextTIMESTAMP'] = df.TIMESTAMP.shift(-1).ffill()
df

enter image description here

aggs = dict(A=['mean', 'count', 'first', 'last'], State=['first'],
            TIMESTAMP={'Start': 'first'}, NextTIMESTAMP={'End': 'last'})
df.groupby('StateGroup').agg(aggs)

enter image description here