Pandas 按主机名分组。按小时计算的会话平均值(在主机上)

Pandas Grouping by Hostname. Average of Sessions(on host) by Hour

数据框看起来像这样。

              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)

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

这是一个基于您提供的数据的示例。我添加了将日期转换为日期时间(如果它们是对象)并将日期时间设置为 datetimeindex 以便使用 resample 的步骤。它会是这样的:

import pandas as pd
import numpy as np
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']))
df.resample('H').mean()

实际上,您可以修改此示例以适应其他目的。据我了解您的问题,您想要计算每小时的平均会话数。如果您需要其他 groupby.s

,请检查 resample-功能

替代方法是将 datetime 分开,然后取平均值:

df['datetime'] =  pd.to_datetime(df['datetime'])
df['Date'] = [x.strftime('%Y-%m-%d') for x in df['datetime'].tolist()]
df['Time'] = ['%s:00' % x.strftime('%H') for x in df['datetime'].tolist()]
df_1 = df.groupby(['Date', 'Time', 'hostname']).mean()

这给出了

编辑:请参阅 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

此处唯一的改进是采用带有时间戳的时钟格式的小时索引。

另一件没有解决但超出此特定问题范围的事情是日期时间列中是否有多天。我将在每天每个数据帧中分离我的数据帧来处理这个问题。但是我是否应该找到更好的方法来处理每一天,我会将其添加到我的解决方案中。