【问题标题】:Find difference between maximum value of group and current row with R用R查找组的最大值与当前行之间的差异
【发布时间】:2018-07-28 06:20:19
【问题描述】:

类似于这个问题here,我试图找出一个组的最大值和当前行的值之间的差异。

例如,如果我有以下数据集:

ID <- c(1,1,1,2,2,2,2,3,3)
Value <- c(2,3,5,2,5,8,17,3,5)
group <- data.frame(Subject=ID, pt=Value)

我将如何创建一个名为“diff”的新列,该列将是当前行的值与该组中的最大值之间的差异?

感谢您的帮助!

【问题讨论】:

  • group %&gt;% group_by(ID) %&gt;% mutate(diff=max(Value)-Value)?你有什么尝试吗?如果是这样,请提供建议,以便我们查看哪些内容不适合您。
  • 我正在尝试使用我链接的 data.table 方法,但没有任何成功。
  • 好吧......如果我们看到您的代码并纠正您的尝试,它通常会有所帮助(并且更相关/更容易被您吸收)。如果您不包含代码和错误或不正确的输出,我们无法更正代码中的小错误。

标签: r dplyr data.table tidyr


【解决方案1】:

OP 尝试了data.table 解决方案。在这里,我们受益于同时通过引用进行分组和更新。

library(data.table)
setDT(group)[, diff := max(pt) - pt, by = Subject][]
   Subject pt diff
1:       1  2    3
2:       1  3    2
3:       1  5    0
4:       2  2   15
5:       2  5   12
6:       2  8    9
7:       2 17    0
8:       3  3    2
9:       3  5    0

数据

ID <- c(1,1,1,2,2,2,2,3,3)
Value <- c(2,3,5,2,5,8,17,3,5)
group <- data.frame(Subject=ID, pt=Value)

基准测试

在撰写本文时,发布了 5 个答案,包括 Frank's comment 关于 data.table 方法的效率。所以,我想知道这五个解决方案中哪一个最快。

  1. r2evans
  2. 我的
  3. Frank
  4. harelhan
  5. JonMinton

一些解决方案会修改 data.frame。为确保公平比较,另外,

OP 需要创建一个名为“diff”的新列。为了比较,所有结果都应返回包含三列的group。一些答案进行了相应的修改。 harelhan 的答案需要大量修改才能消除错误。

随着 group 的修改,所有基准测试运行都以带有两列的 group 的新副本开始。

基准是根据行数和组的份额参数化的,即,组的数量会随着问题的大小而变化,以便进行扩展。

library(data.table)
library(dplyr)
library(bench)
bm <- press(
  # n_row = c(1E2, 1E4, 1E5, 1E6),
  n_row = c(1E2, 1E4, 1E5),
  grp_share = c(0.01, 0.1, 0.5, 0.9),
  {
    n_grp <- grp_share * n_row
    set.seed(1)
    group0 <- data.frame(
      Subject = sample(n_grp, n_row, TRUE),
      pt = as.numeric(rpois(n_row, 100)))
    mark(
      r2Evans = {
        group <- copy(group0)
        group <- group %>% 
          group_by(Subject) %>% 
          mutate(diff = max(pt) - pt)
        group
      },
      Uwe = {
        group <- copy(group0)
        setDT(group)[, diff := max(pt) - pt, by = Subject]
        group
      },
      Frank = {
        group <- copy(group0)
        setDT(group)[, mx := max(pt), by=Subject][, diff := mx - pt][, mx := NULL]
        group
      },
      harelhan = {
        group <- copy(group0)
        max_group <- group %>% group_by(Subject) %>% summarize(max_val = max(pt))
        group <- left_join(group, max_group[, c("Subject", "max_val")], by = "Subject")
        group$diff <- group$max_val - group$pt
        group <- group %>% select(-max_val)
        group
      },
      JonMinton = {
        group <- copy(group0)
        group <- group %>% 
          group_by(Subject) %>% 
          mutate(max_group_val = max(pt)) %>% 
          ungroup() %>% 
          mutate(diff = max_group_val - pt) %>% 
          select(-max_group_val)
        group
      }
    )
  }
)
ggplot2::autoplot(bm)

【讨论】:

【解决方案2】:

使用您的示例数据并将逻辑分解为更小的步骤:

library(dplyr)
ID <- c(1,1,1,2,2,2,2,3,3)
Value <- c(2,3,5,2,5,8,17,3,5)
group <- data.frame(Subject=ID, pt=Value)
max_group <- group %>% group_by(ID) %>% summarize(max_val = max(Value))
group <- left_join(group, max_group[,c(ID, max_val)], by = ID)
group$diff <- group$max_val - group$Value

希望这能解决问题。

【讨论】:

  • 当我运行你的代码时,它说。 grouped_df_impl(data, unname(vars), drop) 中的错误:ID 列未知。此外,请显示结果以便验证和比较。谢谢。
【解决方案3】:

基于harelhan 的回答,但带有管道:

require(dplyr)

df <- data_frame(
  id = c(1,1,1,2,2,2,2,3,3),
  value = c(2,3,5,2,5,8,17,3,5)
)
df %>% 
  group_by(id) %>% 
  mutate(max_group_val = max(value)) %>% 
  ungroup() %>% 
  mutate(diff_frm_group_max = max_group_val - value)

 A tibble: 9 x 4
      id value max_group_val diff_frm_group_max
   <dbl> <dbl>         <dbl>              <dbl>
 1     1     2             5                  3
 2     1     3             5                  2
 3     1     5             5                  0
 4     2     2            17                 15
 5     2     5            17                 12
 6     2     8            17                  9
 7     2    17            17                  0
 8     3     3             5                  2
 9     3     5             5                  0

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多