pandas 具有相同小时数的所有值之间的 RMSE
RMSE between all value with same hours with pandas
我有两个数据框:第一个代表模型模拟的输出,第二个代表真实值。我想计算具有相同小时数的所有值之间的 RMSE。基本上我应该计算 24 RMSE 值,每小时一个。
这些是我的数据框的第一列:
date;model
2017-01-01 00:00:00;53
2017-01-01 01:00:00;52
2017-01-01 02:00:00;51
2017-01-01 03:00:00;47.27
2017-01-01 04:00:00;45.49
2017-01-01 05:00:00;45.69
2017-01-01 06:00:00;48.07
2017-01-01 07:00:00;45.67
2017-01-01 08:00:00;45.48
2017-01-01 09:00:00;42.06
2017-01-01 10:00:00;46.86
2017-01-01 11:00:00;48.02
2017-01-01 12:00:00;49.57
2017-01-01 13:00:00;48.69
2017-01-01 14:00:00;46.91
2017-01-01 15:00:00;49.43
2017-01-01 16:00:00;50.45
2017-01-01 17:00:00;53.3
2017-01-01 18:00:00;59.07
2017-01-01 19:00:00;61.71
2017-01-01 20:00:00;56.26
2017-01-01 21:00:00;55
2017-01-01 22:00:00;54
2017-01-01 23:00:00;52
2017-01-02 00:00:00;53
和
date;real
2017-01-01 00:00:00;55
2017-01-01 01:00:00;55
2017-01-01 02:00:00;55
2017-01-01 03:00:00;48.27
2017-01-01 04:00:00;48.49
2017-01-01 05:00:00;48.69
2017-01-01 06:00:00;49.07
2017-01-01 07:00:00;49.67
2017-01-01 08:00:00;49.48
2017-01-01 09:00:00;50.06
2017-01-01 10:00:00;50.86
2017-01-01 11:00:00;50.02
2017-01-01 12:00:00;33.57
2017-01-01 13:00:00;33.69
2017-01-01 14:00:00;33.91
2017-01-01 15:00:00;33.43
2017-01-01 16:00:00;33.45
2017-01-01 17:00:00;33.3
2017-01-01 18:00:00;33.07
2017-01-01 19:00:00;33.71
2017-01-01 20:00:00;33.26
2017-01-01 21:00:00;33
2017-01-01 22:00:00;33
2017-01-01 23:00:00;33
2017-01-02 00:00:00;33
由于我考虑的是一年,每次 RMSE 计算我都必须考虑 365 的值。
到目前为止,我只能读取数据帧。一种选择是在 1-24 之间设置一个周期,并尝试通过 dfr[dfr.index.hour == i-th hours].
创建 24 个新数据帧
你有更优雅高效的解决方案吗?
谢谢
您需要向 by=
提供一个获取日期并提取小时的函数。
import pandas as pd
from time import strptime
df = pd.DataFrame([
['2017-01-01 00:00:00', 53],
['2017-01-01 01:00:00', 52],
['2017-01-02 00:00:00', 53],
['2017-01-03 01:00:00', 50],
['2017-01-04 00:00:00', 53]
], columns=['date', 'model'])
def group_fun(ix):
return strptime(df['date'][ix], '%Y-%m-%d %H:%M:%S').tm_hour
print(df.groupby(by=group_fun).std())
model
0 0.000000
1 1.414214
RMSE 取决于配对顺序,因此您应该先将 model
加入 real
数据,然后按小时分组并计算您的 RMSE:
def rmse(group):
if len(group) == 0:
return np.nan
s = (group['model'] - group['real']).pow(2).sum()
return np.sqrt(s / len(group))
result = (
df1.merge(df2, on='date')
.assign(hour=lambda x: x['date'].dt.hour)
.groupby('hour')
.apply(rmse)
)
结果:
hour
0 14.21267
1 3.00000
2 4.00000
3 1.00000
4 3.00000
5 3.00000
6 1.00000
7 4.00000
8 4.00000
9 8.00000
10 4.00000
11 2.00000
12 16.00000
13 15.00000
14 13.00000
15 16.00000
16 17.00000
17 20.00000
18 26.00000
19 28.00000
20 23.00000
21 22.00000
22 21.00000
23 19.00000
dtype: float64
说明
代码的作用如下:
merge
:根据date
索引 将两个数据框组合在一起
assign
:创建一个新列hour
,从date
索引中提取
groupby
:根据 hour
值 对行进行分组
apply
允许您编写自定义聚合器。所有 hour = 0
的行将被发送到 rmse
函数(我们的自定义函数),接下来将发送所有 hour = 1
的行。例如:
date hour model real
2017-01-01 00:00:00 0 ... ...
2017-01-02 00:00:00 0 ... ...
2017-01-03 00:00:00 0 ... ...
2017-01-04 00:00:00 0 ... ...
--------------------------------------
2017-01-01 01:00:00 1 ... ...
2017-01-02 01:00:00 1 ... ...
2017-01-03 01:00:00 1 ... ...
2017-01-04 01:00:00 1 ... ...
--------------------------------------
2017-01-01 02:00:00 2 ... ...
2017-01-02 02:00:00 2 ... ...
2017-01-03 02:00:00 2 ... ...
2017-01-04 02:00:00 2 ... ...
--------------------------------------
2017-01-01 03:00:00 3 ... ...
2017-01-02 03:00:00 3 ... ...
2017-01-03 03:00:00 3 ... ...
2017-01-04 03:00:00 3 ... ...
然后将每个块发送到我们的自定义函数:rmse(group=<a chunk>)
。在函数中,我们将该块缩减为一个数字:它的 RMSE。这就是你如何得到 24 个 RMSE 数字的结果。
我有两个数据框:第一个代表模型模拟的输出,第二个代表真实值。我想计算具有相同小时数的所有值之间的 RMSE。基本上我应该计算 24 RMSE 值,每小时一个。
这些是我的数据框的第一列:
date;model
2017-01-01 00:00:00;53
2017-01-01 01:00:00;52
2017-01-01 02:00:00;51
2017-01-01 03:00:00;47.27
2017-01-01 04:00:00;45.49
2017-01-01 05:00:00;45.69
2017-01-01 06:00:00;48.07
2017-01-01 07:00:00;45.67
2017-01-01 08:00:00;45.48
2017-01-01 09:00:00;42.06
2017-01-01 10:00:00;46.86
2017-01-01 11:00:00;48.02
2017-01-01 12:00:00;49.57
2017-01-01 13:00:00;48.69
2017-01-01 14:00:00;46.91
2017-01-01 15:00:00;49.43
2017-01-01 16:00:00;50.45
2017-01-01 17:00:00;53.3
2017-01-01 18:00:00;59.07
2017-01-01 19:00:00;61.71
2017-01-01 20:00:00;56.26
2017-01-01 21:00:00;55
2017-01-01 22:00:00;54
2017-01-01 23:00:00;52
2017-01-02 00:00:00;53
和
date;real
2017-01-01 00:00:00;55
2017-01-01 01:00:00;55
2017-01-01 02:00:00;55
2017-01-01 03:00:00;48.27
2017-01-01 04:00:00;48.49
2017-01-01 05:00:00;48.69
2017-01-01 06:00:00;49.07
2017-01-01 07:00:00;49.67
2017-01-01 08:00:00;49.48
2017-01-01 09:00:00;50.06
2017-01-01 10:00:00;50.86
2017-01-01 11:00:00;50.02
2017-01-01 12:00:00;33.57
2017-01-01 13:00:00;33.69
2017-01-01 14:00:00;33.91
2017-01-01 15:00:00;33.43
2017-01-01 16:00:00;33.45
2017-01-01 17:00:00;33.3
2017-01-01 18:00:00;33.07
2017-01-01 19:00:00;33.71
2017-01-01 20:00:00;33.26
2017-01-01 21:00:00;33
2017-01-01 22:00:00;33
2017-01-01 23:00:00;33
2017-01-02 00:00:00;33
由于我考虑的是一年,每次 RMSE 计算我都必须考虑 365 的值。
到目前为止,我只能读取数据帧。一种选择是在 1-24 之间设置一个周期,并尝试通过 dfr[dfr.index.hour == i-th hours].
创建 24 个新数据帧你有更优雅高效的解决方案吗?
谢谢
您需要向 by=
提供一个获取日期并提取小时的函数。
import pandas as pd
from time import strptime
df = pd.DataFrame([
['2017-01-01 00:00:00', 53],
['2017-01-01 01:00:00', 52],
['2017-01-02 00:00:00', 53],
['2017-01-03 01:00:00', 50],
['2017-01-04 00:00:00', 53]
], columns=['date', 'model'])
def group_fun(ix):
return strptime(df['date'][ix], '%Y-%m-%d %H:%M:%S').tm_hour
print(df.groupby(by=group_fun).std())
model
0 0.000000
1 1.414214
RMSE 取决于配对顺序,因此您应该先将 model
加入 real
数据,然后按小时分组并计算您的 RMSE:
def rmse(group):
if len(group) == 0:
return np.nan
s = (group['model'] - group['real']).pow(2).sum()
return np.sqrt(s / len(group))
result = (
df1.merge(df2, on='date')
.assign(hour=lambda x: x['date'].dt.hour)
.groupby('hour')
.apply(rmse)
)
结果:
hour
0 14.21267
1 3.00000
2 4.00000
3 1.00000
4 3.00000
5 3.00000
6 1.00000
7 4.00000
8 4.00000
9 8.00000
10 4.00000
11 2.00000
12 16.00000
13 15.00000
14 13.00000
15 16.00000
16 17.00000
17 20.00000
18 26.00000
19 28.00000
20 23.00000
21 22.00000
22 21.00000
23 19.00000
dtype: float64
说明
代码的作用如下:
merge
:根据date
索引 将两个数据框组合在一起
assign
:创建一个新列hour
,从date
索引中提取groupby
:根据hour
值 对行进行分组
apply
允许您编写自定义聚合器。所有 hour = 0
的行将被发送到 rmse
函数(我们的自定义函数),接下来将发送所有 hour = 1
的行。例如:
date hour model real
2017-01-01 00:00:00 0 ... ...
2017-01-02 00:00:00 0 ... ...
2017-01-03 00:00:00 0 ... ...
2017-01-04 00:00:00 0 ... ...
--------------------------------------
2017-01-01 01:00:00 1 ... ...
2017-01-02 01:00:00 1 ... ...
2017-01-03 01:00:00 1 ... ...
2017-01-04 01:00:00 1 ... ...
--------------------------------------
2017-01-01 02:00:00 2 ... ...
2017-01-02 02:00:00 2 ... ...
2017-01-03 02:00:00 2 ... ...
2017-01-04 02:00:00 2 ... ...
--------------------------------------
2017-01-01 03:00:00 3 ... ...
2017-01-02 03:00:00 3 ... ...
2017-01-03 03:00:00 3 ... ...
2017-01-04 03:00:00 3 ... ...
然后将每个块发送到我们的自定义函数:rmse(group=<a chunk>)
。在函数中,我们将该块缩减为一个数字:它的 RMSE。这就是你如何得到 24 个 RMSE 数字的结果。