首页 > 解决方案 > Pandas 按主机名分组。平均会话数(在主机上)(按小时)

问题描述

数据框看起来像这样。

              datetime   hostname  sessions
0  2020-10-27 00:00:05  server001        22
1  2020-10-27 00:00:10  server001        25
2  2020-10-27 00:00:15  server001        21
3  2020-10-27 01:00:05  server001        30
4  2020-10-27 01:00:10  server001        30
5  2020-10-27 01:00:15  server001        35
6  2020-10-27 00:00:05  server002        15
7  2020-10-27 00:00:10  server002        10
8  2020-10-27 00:00:15  server002        11
9  2020-10-27 01:00:05  server002        19
10 2020-10-27 01:00:10  server002        22
11 2020-10-27 01:00:15  server002        18

我试图按单个主机名显示每小时的平均会话数。

所以我会得到这样的东西。

              datetime   hostname  sessions
0  2020-10-27 00:00:00  server001        23
1  2020-10-27 01:00:00  server001        32
2  2020-10-27 00:00:00  server002        12
3  2020-10-27 01:00:00  server002        20

我认为我的分组错误,因为在尝试此操作时,我最终得到的通常是按小时按日期排序的任何给定主机名每小时的最大平均值。

例如,我可能会看到类似

                hostname   datetime     sessions
0  2020-10-27  server001   00:00:00           23
1  2020-10-27              01:00:00           32
2  2020-10-27  server002   02:00:00           12
3  2020-10-27  server003   03:00:00           20

而不是列出的每个主机名的完整 24 小时。

我试过的代码是:

df = df.groupby(['hostname']).resample(
        'H', on='datetime'
        ).agg({'sessions': 'mean'}).round(0).astype(int)

我需要做什么才能得到想要的结果?

标签: pythonpandasdatetimepandas-groupbyaverage

解决方案


编辑:请在此处查看Serge de Gosson de Varnnes 的第二个示例。这正是我想要的。

我相信我已经找到了答案。我犯的第一个错误是没有按小时创建索引。我相信Amit Kumar说的是这个,但当时我不太明白他的意思。并且Serge de Gosson de Varnnes也在他的示例中为数据设置了索引。

我将使用Serge de Gosson de Varnnes 的数据插入示例,因此任何发现此示例的人都可以直接使用示例并检查输出:

import pandas as pd

d ={'datetime' :['2020-10-27 00:00:05','2020-10-27 00:00:10','2020-10-27 00:00:15','2020-10-27 01:00:05','2020-10-27 01:00:10','2020-10-27 01:00:15','2020-10-27 00:00:05','2020-10-27 00:00:10','2020-10-27 00:00:15','2020-10-27 01:00:05','2020-10-27 01:00:10','2020-10-27 01:00:15'],
   'hostname':['server001','server001','server001','server001','server001','server001','server002','server002','server002','server002','server002','server002'],
   'sessions':[ 22,25,21 ,30,30,35,15,10, 11,19,22,18]}       
df = pd.DataFrame(data=d)
df['datetime'] =  pd.to_datetime(df['datetime'])
df = df.set_index(pd.DatetimeIndex(df['datetime']))

hour_index = df.index.hour

df = groupby([hour_index, 'hostname'])['sessions'].mean().round(0).astype(int)

with pd.option_context(
        'display.max_rows',
         None,
         'display.max_columns',
         None
         ):
    print(df)

此处使用 round 和 astype 方法向上舍入到最接近的整数。这不是我之前指定的内容,因为我已经知道如何处理它,但为了完整起见,我将其放在这里。

这里的 with 语句是为了允许打印完整的数据帧(要小心大数据帧,因为这可能是一次在屏幕上打印的大量数据)。

输出:

datetime  hostname 
0         server001    23
          server002    12
1         server001    32
          server002    20

这里唯一好的改进是按小时索引以带有时间戳的时钟格式。

这没有解决的另一件事,但超出了这个特定问题的范围是 datetime 列中是否有多天。我将在每天每个数据帧中分离我的数据帧来处理这个问题。但是如果我能找到更好的方式来处理每一天,我会将其添加到我的解决方案中。


推荐阅读