如何在包含两行信息的同时对数据框进行分组?
How to group a data frame while containing information about two rows?
我是 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
以某种方式,我想对这些状态进行分组并获取每个状态的开始和结束时间戳并将其保存在一个时间间隔中。有谁知道比循环遍历数据框更快的方法吗?
这应该会有帮助。使用大量 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)
我是 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
以某种方式,我想对这些状态进行分组并获取每个状态的开始和结束时间戳并将其保存在一个时间间隔中。有谁知道比循环遍历数据框更快的方法吗?
这应该会有帮助。使用大量 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)