【问题标题】:pandas how to groupby a period time and then get back a df after filtration inside the group?熊猫如何分组一段时间,然后在组内过滤后取回一个df?
【发布时间】:2017-08-08 09:44:24
【问题描述】:

基本上,现在我有一组来自某些路由器(AP)的数据。路由器会每 3 秒探测一次用户的设备,并给我们用户的 MAC 号(tag_mac)。

为了清理这些数据(因为在一段时间内,如果用户靠近其他 AP,不同的 AP 会给我们返回相同的 tag_macs),我只需要每个 AP 中信号最强(由 rssi 表示)的 AP 10 秒(取平均值)。这是我的数据样本。


         ap_mac  rssi       tag_mac                time
0  048b422149fa   -63  a40dbc018db7 2017-07-01 08:00:00
1  048b4223e63d   -72  a40dbc018db7 2017-07-01 08:00:00
2  048b4223e63d   -72  a40dbc018db7 2017-07-01 08:00:00
3  048b4223e63d   -72  a40dbc018db7 2017-07-01 08:00:00
4  048b4223e63d   -72  a40dbc018db7 2017-07-01 08:00:00
5  048b422149ff   -50  30b49e3715d0 2017-07-01 08:00:00
6  048b422149ff   -50  30b49e3715d0 2017-07-01 08:00:00
7  048b422149ff   -50  30b49e3715d0 2017-07-01 08:00:00
8  048b422149ff   -50  30b49e3715d0 2017-07-01 08:00:00
9  048b422149ff   -50  30b49e3715d0 2017-07-01 08:00:00

我需要的是一个过滤的数据帧,其中我删除的所有行在每 10 秒的时间段内具有较弱的 rssi。所以我剩下的是一个清理过的数据,对于每个 tag_mac,我只有具有最强 rssi 的 ap_macs。

有人可以帮我吗? 谢谢!

【问题讨论】:

  • 您的time 列似乎根本没有变化,但您声称路由器会每 3 秒探测用户的设备。同一个 AP mac 的不同行的时间不应该改变吗?
  • @Abdou hmmm...好吧,我会检查我的数据,但这正是我的意思。
  • 例如 AP MAC 048b4223e63d 被探测了四次,但所有这些探测同时发生:2017-07-01 08:00:00

标签: python pandas dataframe pandas-groupby


【解决方案1】:

我不知道我是否理解您的问题,但您可以使用 pandas Grouper,例如:

df['time'] = pd.to_datetime(df['time'])
df = df.set_index('time')
result = df.groupby([pd.TimeGrouper(freq='10S'),'ap_mac','tag_mac']).mean().reset_index()
result.groupby(['time','tag_mac'])[['ap_mac','rssi']].max()

编辑:

我修改了你的表格只是为了看看代码是如何工作的:

         ap_mac  rssi       tag_mac                time
0  048b422149fa   -63  a40dbc018db7 2017-07-01 08:00:00
1  048b4223e63d   -72  a40dbc018db7 2017-07-01 08:00:10
2  048b4223e63d   -72  a40dbc018db7 2017-07-01 08:00:15
3  048b4223e63d   -72  a40dbc018db7 2017-07-01 08:00:00
4  048b4223e63d   -72  a40dbc018db7 2017-07-01 08:00:00
5  048b422149ff   -50  30b49e3715d0 2017-07-01 08:00:00
6  048b422149ff   -50  30b49e3715d0 2017-07-01 08:00:30
7  048b422149ff   -50  30b49e3715d0 2017-07-01 08:00:12
8  048b422149ff   -50  30b49e3715d0 2017-07-01 08:00:00
9  048b422149ff   -50  30b49e3715d0 2017-07-01 08:00:00

您想按时间(每 10 秒)、ap_mactag_mac 进行分组。

您首先使用 pd.to_datetime 将时间列转换为日期时间

df['time'] = pd.to_datetime(df['time'])

为了使用 TimeGrouper,您将时间作为索引(仅适用于 DateTimeIndex)

df = df.set_index('time')

然后您执行 groupby 以每 10 秒获取每个 ap_mac 的每个 tag_mac 的平均值。

result = df.groupby([pd.TimeGrouper(freq='10S'),'ap_mac','tag_mac']).mean().reset_index()

最后,

result.groupby(['time','tag_mac'])[['ap_mac', 'rssi']].max()

输出:

                                        ap_mac          rssi
time                    tag_mac         
2017-07-01 08:00:00     30b49e3715d0    048b422149ff    -50
                        a40dbc018db7    048b4223e63d    -63
2017-07-01 08:00:10     30b49e3715d0    048b422149ff    -50
                        a40dbc018db7    048b4223e63d    -72
2017-07-01 08:00:30     30b49e3715d0    048b422149ff    -50

【讨论】:

  • 我希望我不是太不清楚。我想要的是:每 10 秒内,一个 tag-mac 可能会接受来自多个 ap-mac 的信号,但我只想要包含在那 10 秒内具有最强平均 rssi 的单个 ap-mac 的行。
  • 谢谢!它几乎可以按我的意愿工作。但似乎你正在返回 max() 的东西,但你没有指定它是 rssi 的最大值?我需要的实际上是这 10 秒内同一 ap_mac 的最大平均值。所以我只能声称,在那 10 秒内,tag_mac 仅被具有最强平均 rssi 的 ap_mac 检测到。
  • 谢谢!这是非常有效的!但是由于您使用标签和ap分组,所以它的形状只是一个1列数据框,以组作为索引(如果我错了,请纠正我),那么我们如何从结果回到原来的4列?
  • 另外,它是否应该是一个语法错误 result = df.groupby(['ap_mac', 'tag_mac',pd.TimeGrouper(freq='10S')]).mean () 代码>?为什么会有“df”。在钥匙之前?
  • 你是对的,你可以做 df.groupby(['ap_mac', 'tag_mac', pd.TimeGrouper(freq='10S']).mean()。
【解决方案2】:

我假设 df 为 DataFrame

#this makes sure that the 'date' column is in the required format
df['time'] = pd.to_datetime(df['time'] , format='%Y-%m-%d %H:%M:%S')

new_df = pd.DataFrame(columns=['ap_mac','tag_mac','rssi','to','from'])

#start date - first date in the dataframe 'df'
start = pd.Timestamp(df.loc[0,'time'])

#end date is the last date in the dataframe 'df'
end = pd.Timestamp(df.loc[df.shape[0]-1,'time'])


upper = lower = start

indices_array =[]

while (end - upper >= pd.Timedelta(seconds=10)):

    upper = upper + pd.Timedelta(seconds=10)
    #data within a 10 second range is extracted into the variable data

    data = df[upper>df['time']][df['time']>=lower]

    for i in data['tag_mac'].unique():

        var = data.loc[data['tag_mac']==i].groupby('ap_mac').mean()
    #in the new_df rssi contains average values
        new_df = new_df.append({'rssi':var.max()[0],'ap_mac':var.idxmax()[0],'tag_mac':i,'to':upper,'from':lower},ignore_index=True)

    lower = upper

正如您所提到的,您的庞大数据集被压缩到 DataFrame new_df 中,仅包含您需要的值

我在数据框new_df 中添加了新列tofrom,显示了读数存在的时间范围

new_df 包含所有tag_macs 及其对应的ap_macs,它们的最大平均 rssi 值每十秒采样一次。

如果您遇到任何困难,请随时发表评论

【讨论】:

  • 实际上我有一个超过 500 万行的固定 df。时间是给定的列,所以我不需要随着时间的增长更新 df。这是你的代码在做什么?
  • 是的,每 10 秒内,这就是为什么我也想按时间段分组。
  • 每个AP只每3秒发送一次数据,但是由于我有很多aps,所以是的,它是连续的。
  • 是的,我愿意。我希望我不是太不清楚。我想要的是:每 10 秒内,一个 tag-mac 可能会接受来自多个 ap-mac 的信号,但我只想要包含在那 10 秒内具有最强平均 rssi 的单个 ap-mac 的行。
  • 谢谢!这正是我所需要的!还有一件事,在每10秒内,1个ap可能会检测到相同的tag_mac 3次,而对于单行,它可能是最大值,但平均而言它可能低于另一个ap。有什么办法可以修改吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-25
  • 2021-01-05
  • 1970-01-01
  • 2021-05-26
  • 1970-01-01
  • 2019-04-15
  • 2021-11-20
相关资源
最近更新 更多