首页 > 解决方案 > 按特定条件的出现对数据框进行分组

问题描述

我正在尝试分析 Pandas 中的一些无人机飞行日志。日志有时间戳、无人机发送的消息和一些感官数据。每几条消息都会发送一个位置。我现在想在位置消息之前按顺序对所有行进行分组(或者换句话说,每次出现位置消息时将整个数据帧分成组)。这些消息不一定以设定的频率出现。

这里有一个简化的例子:

这个

id  timestamp       message  additional_sensor_value
 1   12:10:44         speed                      144     
 2   12:10:46      position                       23
 3   12:10:63   orientation                      222
 4   12:10:82        status                        2
 5   12:11:02      position                       63
 6   12:11:24         speed                       52  
 7   12:11:43      position                      127

应该像这样分组:

id  timestamp       message  additional_sensor_value
12:10:46
 1   12:10:44         speed                      144     
 2   12:10:46      position                       23

12:11:02
 3   12:10:63   orientation                      222
 4   12:10:82        status                        2
 5   12:11:02      position                       63

12:11:43
 6   12:11:24         speed                       52  
 7   12:11:43      position                      127

目标是获取每个位置出现的附加传感器值的平均值,以获取所有记录数据的散点图,而不仅仅是像我现在在下面的示例中那样的位置数据。

无人机飞行散点图

如果您有任何其他建议如何以更好的方式解决此问题,我很乐意听到,但我尽量避免使用 for 循环,因为这些数据帧可能非常大(> 1 百万行)并且我想要尽可能快地保持它。

标签: pythonpandas

解决方案


Series通过比较创建助手messageSeries.eq然后通过索引更改顺序[::-1]并创建组Series.cumsum,最后更改顺序为原始:

g = df['message'].eq('position').iloc[::-1].cumsum().iloc[::-1]

for _, x in df.groupby(g, sort=False):
    print (x['timestamp'].iat[-1])
    print (x)
12:10:46
   id timestamp   message  additional_sensor_value
0   1  12:10:44     speed                      144
1   2  12:10:46  position                       23
12:11:02
   id timestamp      message  additional_sensor_value
2   3  12:10:63  orientation                      222
3   4  12:10:82       status                        2
4   5  12:11:02     position                       63
12:11:43
   id timestamp   message  additional_sensor_value
5   6  12:11:24     speed                       52
6   7  12:11:43  position                      127

如果需要像这样聚合GroupBy.agg使用g

g = df['message'].eq('position').iloc[::-1].cumsum().iloc[::-1]
df = df.groupby(g, sort=False).agg(avg=('additional_sensor_value', 'mean'),
                                   time = ('timestamp','last'))
print (df)
               avg      time
message                     
3        83.500000  12:10:46
2        95.666667  12:11:02
1        89.500000  12:11:43

推荐阅读