【问题标题】:How to group a data frame while containing information about two rows?如何在包含有关两行的信息的同时对数据框进行分组?
【发布时间】:2017-01-04 14:44:59
【问题描述】:

我是 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 列中的值是稳定 (S)、增加 (I) 或减少 (D) 的时间间隔。

此时,我使用 for 循环来比较行并计算这些值之间的斜率。只要每次迭代的斜率符号不改变,间隔的结束时间戳就会更新。这会产生像 Interval(begin, end, state) 这样的间隔。上面示例的结果将是:

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

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

【问题讨论】:

    标签: python pandas dataframe timestamp pandas-groupby


    【解决方案1】:

    这应该会有所帮助。大量使用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
    

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

    【讨论】:

    • 这绝对有帮助,正是我想要的。非常感谢!
    • 我有一个三对一的特价商品:df['State'] = np.where(df.A.pct_change() > 0, "I", np.where(df.A. pct_change()
    猜你喜欢
    • 2021-08-11
    • 1970-01-01
    • 2018-12-24
    • 1970-01-01
    • 2018-11-02
    • 2015-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多