在 R 中使用 h2o 聚合 Max

Aggregating Max using h2o in R

我已经开始使用 h2o 来聚合大型数据集,并且在尝试使用 h2o 的 h2o.group_by 函数聚合最大值时发现了奇怪的行为。我的数据框通常包含变量,这些变量包含给定分组的部分或全部 NA。下面是一个示例数据框。

df <- data.frame("ID" = 1:16)
df$Group<- c(1,1,1,1,2,2,2,3,3,3,4,4,5,5,5,5)
df$VarA <- c(NA_real_,1,2,3,12,12,12,12,0,14,NA_real_,14,16,16,NA_real_,16)
df$VarB <- c(NA_real_,NA_real_,NA_real_,NA_real_,10,12,14,16,10,12,14,16,10,12,14,16)
df$VarD <- c(10,12,14,16,10,12,14,16,10,12,14,16,10,12,14,16)

   ID Group VarA VarB VarD
1   1     1   NA   NA   10
2   2     1    1   NA   12
3   3     1    2   NA   14
4   4     1    3   NA   16
5   5     2   12   10   10
6   6     2   12   12   12
7   7     2   12   14   14
8   8     3   12   16   16
9   9     3    0   10   10
10 10     3   14   12   12
11 11     4   NA   14   14
12 12     4   14   16   16
13 13     5   16   10   10
14 14     5   16   12   12
15 15     5   NA   14   14
16 16     5   16   16   16

在此数据框中,Group == 1 完全缺少 VarB 的数据(但这是重要的信息,因此最大值聚合的输出应为 NA),而 Group == 1 VarA 只有一个缺少值,因此最大值应为 3。

这是一个 link,其中包含 na.methods 参数 (https://docs.h2o.ai/h2o/latest-stable/h2o-docs/data-munging/groupby.html) 的行为。

如果我如下设置 na.methods = 'all',则对于 Vars A 和 B,第 1 组的聚合输出为 NA(这不是我想要的,但我完全理解这种行为)。

h2o_agg <-  h2o.group_by(data = df_h2o, by = 'Group', max(), gb.control = list(na.methods = "all"))

  Group max_ID max_VarA max_VarB max_VarD
1     1      4      NaN      NaN       16
2     2      7       12       14       14
3     3     10       14       16       16
4     4     12      NaN       16       16
5     5     16      NaN       16       16

如果我如下设置 na.methods = 'rm',则第 1 组的聚合输出对于 VarA 为 3(这是所需的输出并且完全有意义)但对于 VarB 为 -1.80e308(这不是什么我想要,但我不理解这种行为)。

h2o_agg <-  h2o.group_by(data = df_h2o, by = 'Group', max(), gb.control = list(na.methods = "rm"))

  Group max_ID max_VarA  max_VarB max_VarD
  <int>  <int>    <int>     <dbl>    <int>
1     1      4        3 -1.80e308       16
2     2      7       12  1.4 e  1       14
3     3     10       14  1.6 e  1       16
4     4     12       14  1.6 e  1       16
5     5     16       16  1.6 e  1       16

同样,如果设置 na.methods = 'ignore',我会得到相同的输出。

h2o_agg <-  h2o.group_by(data = df_h2o, by = 'Group', max(), gb.control = list(na.methods = "ignore"))

  Group max_ID max_VarA  max_VarB max_VarD
  <int>  <int>    <int>     <dbl>    <int>
1     1      4        3 -1.80e308       16
2     2      7       12  1.4 e  1       14
3     3     10       14  1.6 e  1       16
4     4     12       14  1.6 e  1       16
5     5     16       16  1.6 e  1       16

我不确定为什么像特定组中给定变量的完全缺失数据这样常见的事情被赋予 -1.80e308 的值?我在 dplyr 中尝试了相同的工作流程并得到了符合我期望的结果(但这不是解决方案,因为我无法在 dplyr 中处理这种大小的数据集,因此我需要 h2o 中的解决方案)。我意识到 dplyr 给我 -inf 值而不是 NA,我可以轻松地将 -1.80e308-Inf 重新编码为 NA,但我试图确保这不是症状h2o 中的一个更大的问题(或者当我试图在 h2o 中聚合时,我的代码没有做一些根本性的错误)。我还必须聚合规范化数据集,这些数据集的值通常与 -1.80e308 大致相似,因此我不想不小心将合法值重新编码为 NA。

library(dplyr)
df %>%
  group_by(Group) %>% 
  summarise(across(everything(), ~max(.x, na.rm = TRUE)))

  Group    ID  VarA  VarB  VarD
  <dbl> <int> <dbl> <dbl> <dbl>
1     1     4     3  -Inf    16
2     2     7    12    14    14
3     3    10    14    16    16
4     4    12    14    16    16
5     5    16    16    16    16

 

不确定如何使用 h2o.group_by() 实现 - 当 运行 你的代码时,我得到了同样奇怪的值。如果您愿意接受一些 hacky 解决方法,您可能想尝试以下方法(我包含了 H2O 初始化部分以供将来参考):

  1. 将您的框架转换为长格式,即 key-value 表示
  2. 按组拆分并使用 h2o.ddply()
  3. 应用聚合函数
  4. 将您的框架转换回宽格式
## initialize h2o
library(h2o)

h2o.init(
  nthreads = parallel::detectCores() * 0.5
)

df_h2o = as.h2o(
  df
)

## aggregate per group
df_h2o |> 
  
  # convert to long format
  h2o.melt(
    id_vars = "Group"
    , skipna = TRUE # does not include `NA` in the result
  ) |> 
  
  # calculate `max()` per group
  h2o.ddply(
    .variables = c("Group", "variable")
    , FUN = function(df) {
      max(df[, 3])
    }
  ) |> 
  
  # convert back to wide format
  h2o.pivot(
    index = "Group"
    , column = "variable"
    , value = "ddply_C1"
  )

# Group ID VarA VarB VarD
#     1  4    3  NaN   16
#     2  7   12   14   14
#     3 10   14   16   16
#     4 12   14   16   16
#     5 16   16   16   16
# 
# [5 rows x 5 columns] 

## shut down h2o instance
h2o.shutdown(
  prompt = FALSE
)

发生这种情况是因为 H2O 认为值 -Double.MAX_VALUE 是可表示的最低 floating-point 数字。该值对应于 -1.80e308。我同意这令人困惑,我认为这是一个错误。您可以在我们的错误跟踪器中提交问题:https://h2oai.atlassian.net/(PUBDEV 项目)