首页 > 解决方案 > 我如何计算每小时的值并将上一小时和下一小时显示到数据框中具有最高值的那一小时?

问题描述

这是我的数据的一小部分样本,包含在更大的 pandas df 中:

    Year    Month   Day Hour    errors
0   2018    10      15  23      149
1   2016    9       21  14      114
2   2018    10      14  23      106
3   2016    5       19  14      100
4   2018    10      19  9       85
5   2017    6       15  10      79
6   2017    6       15  13      76
7   2017    6       15  9       71
8   2016    9       21  15      70
9   2016    9       13  14      65
10  2018    10      14  22      64
11  2019    3       27  16      62
12  2018    10      16  0       60
13  2016    5       19  15      59
14  2018    5       30  9       58
15  2017    6       15  12      52
16  2018    6       15  14      51
17  2016    9       19  16      51
18  2016    9       20  13      51
19  2016    9       21  16      48
20  2018    10      22  12      48

此数据按年月日和小时显示错误数。我知道如何找到每小时最多的错误并对其进行排序,这不是问题。我需要做的是显示错误数量最多的小时数(以及它们各自的月、年和日),但还要显示前一个小时,以及错误数最多的那个小时的下一个小时。我还需要按降序显示此表。

这是我想要的输出的一个例子,但数据不是真实的,我在伪造它,因为我不知道数据的真实值,但提供一个说明性的例子很有用:

    Year    Month   Day Hour    errors
0   2018    10      15  21      120 # Previous hour
1   2018    10      15  22      150 # Hour of the same year, month and day with the biggest number of errors
2   2018    10      15  23      130 # Next hour
3   2016    7       29  16      40  # Previous hour
4   2016    7       29  17      90  # Hour of the same year, month and day with the biggest number of errors
5   2016    7       29  18      20  # Next hour

其余的数据依此类推。这个想法很简单,但我不知道如何组织数据框中的行以这种方式显示。有人可以帮我吗?

非常感谢您提前

标签: pythonpython-3.xpandasdataframe

解决方案


假设我们有以下测试数据:

   Year  Month  Day  Hour  errors
0  2016      5   19    14      51
1  2016      5   19    15      52
2  2016      5   19    16     100
3  2016      5   19    17      54
4  2016      5   19    18      55
5  2016      5   20     8      41
6  2016      5   20     9      42
7  2016      5   20    10     200
8  2016      5   20    11      43
9  2016      5   20    12      44

我们附加一个辅助列maxerr,用 1 标记每天最大错误的行:

df['maxerr'] = None
df.iloc[df.groupby(['Year', 'Month', 'Day']).errors.idxmax().values,-1] = 1

然后我们将这个标记向上和向下传播一行:

df['maxerr'] = df['maxerr'].ffill(limit=1).bfill(limit=1)

在删除所有剩余的(未标记的)行和我们的辅助列之后

df.dropna().drop(columns='maxerr')

我们得到:

   Year  Month  Day  Hour  errors
1  2016      5   19    15      52
2  2016      5   19    16     100
3  2016      5   19    17      54
6  2016      5   20     9      42
7  2016      5   20    10     200
8  2016      5   20    11      43

(如果原始数据不应该按时间排序,我们必须先按 排序df = df.sort_values(['Year', 'Month', 'Day', 'Hour'])

根据以下评论中给出的附加要求进行更新: 为了仅包括与最大错误小时数直接相邻的小时数,我们临时创建一个日期时间索引并将其上采样为小时数。在对数据帧进行上采样后,我们丢弃该索引并像以前一样继续。唯一的区别是,由于插入了 NaN,所有列都转换为浮点数,我们通过 撤消astype(int)

df = df.set_index(pd.to_datetime(df[['Year', 'Month', 'Day', 'Hour']]))
df = df.resample('1H').asfreq()
df = df.reset_index(drop=True)

df['maxerr'] = None
df.iloc[df.groupby(['Year', 'Month', 'Day']).errors.idxmax().values,-1] = 1
df['maxerr'] = df['maxerr'].ffill(limit=1).bfill(limit=1)
df = df.dropna().drop(columns='maxerr').astype(int)

有了这些测试数据:

    Year  Month  Day  Hour  errors
0   2016      5   19    14      51
1   2016      5   19    15      52
2   2016      5   19    16     100
3   2016      5   19    17      54
4   2016      5   19    18      55
5   2016      5   20     8      41
6   2016      5   20     9      42
7   2016      5   20    10     200
8   2016      5   20    12      44
9   2016      5   20    23      45
10  2016      5   21     0     300
11  2016      5   21     1      46

我们得到:

    Year  Month  Day  Hour  errors
1   2016      5   19    15      52
2   2016      5   19    16     100
3   2016      5   19    17      54
19  2016      5   20     9      42
20  2016      5   20    10     200
33  2016      5   20    23      45
34  2016      5   21     0     300
35  2016      5   21     1      46

我们看到第 8 行不包括在内,因为它的第 12 小时不直接在第 7 行中的第 10 小时之后。此外,前一天的第 9 行包含在第 10 行中的 0 小时的最大值。

基于下面评论中给出的附加要求的第二次更新:为了仅当 prev 和 next 都存在时才包含最大错误行以及 prev 和 next 行,并且如果 prev 或 next 缺失则不包含任何内容,我们插入代码第一次更新/行之前的以下行:ffillbfill

df['maxerr'] = df.maxerr + df.errors.shift(-1) + df.errors.shift(1)

如果 prev ( shift(1)) 或 next ( shift(-1)) 缺失,它们会传播NaN到 maxerr。在像之前一样填充和删除NaNs 之后,我们在示例中得到:

    Year  Month  Day  Hour  errors
1   2016      5   19    15      52
2   2016      5   19    16     100
3   2016      5   19    17      54
33  2016      5   20    23      45
34  2016      5   21     0     300
35  2016      5   21     1      46

在这里,排除了 10 小时的最大错误行以及 9 小时的前一行,因为 11 小时(天 = 20)没有行。


推荐阅读