【问题标题】:Calculate median for multiple columns by group based on subsets defined by other columns根据其他列定义的子集按组计算多列的中位数
【发布时间】:2019-02-03 23:02:33
【问题描述】:

我正在尝试根据其他列定义的子集按组计算多列的中位数(但可以用类似的指标代替)。这是我的previous post 的直接后续问题。我试图将通过aggregate 计算中位数合并到@Frank 提供的Map(function(x,y) dosomething, x, y) 解决方案中,但这没有用。让我举例说明:

按组 GRP1 和 GRP2 计算 A 和 B 的中位数

df <- data.frame(GRP1 = c("A","A","A","A","A","A","B","B","B","B","B","B"), GRP2 = c("A","A","A","B","B","B","A","A","A","B","B","B"), A = c(0,4,6,7,0,1,9,0,0,8,3,4), B = c(6,0,4,8,6,7,0,9,9,7,3,0))

med <- aggregate(.~GRP1+GRP2,df,FUN=median)

简单。现在添加定义用于计算中位数的行的列,即应删除具有 NA 的行,列 a 定义用于计算 A 列中的中位数的行,对于列 b 和 B 相同:

a <- c(1,4,7,3,NA,3,7,NA,NA,4,8,1)
b <- c(5,NA,7,9,5,6,NA,8,1,7,2,9)
df1 <- cbind(df,a,b)

如上所述,我尝试过将Mapaggregate 结合使用,但没有奏效。我假设Map 不知道如何处理 GRP1 和 GRP2。

med1 <- Map(function(x,y) aggregate(.~GRP1+GRP2,df1[!is.na(y)],FUN=median), x=df1[,3:4], y=df1[, 5:6])

这是我正在寻找的结果:

  GRP1 GRP2 A B
1    A    A 4 5
2    B    A 9 9
3    A    B 4 7
4    B    B 4 3

任何帮助将不胜感激!

【问题讨论】:

  • 可以像 Frank 在上一篇文章中向您展示的那样:f &lt;- function(x, y) median(x[!is.na(y)]) ; df1[, Map(f, .SD[, 1:2], .SD[, 3:4]), by = .(GRP1, GRP2)]
  • @DavidArenburg 这将是一个非常简洁的答案,因为我不必分别为每一列编码。不幸的是,我收到以下错误消息:&gt; df1[, Map(f, .SD[, 1:2], .SD[, 3:4]), by = .(GRP1, GRP2)] Error in [.data.frame(df1, , Map(f, .SD[, 1:2], .SD[, 3:4]), by = .(GRP1, : unused argument (by = .(GRP1, GRP2))
  • 你当然需要将df1转换成data.table,即setDT(df1)
  • 当然 - 谢谢!
  • @DavidArenburg 冒着暴露我无知的风险:为什么.SD[, 1:2] and .SD[, 3:4] 分别为 3:4 和 5:6 列编码?

标签: r dplyr data.table aggregate plyr


【解决方案1】:

使用data.table

library(data.table)
setDT(df1)

df1[, .(A = median(A[!is.na(a)]), B = median(B[!is.na(b)])), by = .(GRP1, GRP2)]

   GRP1 GRP2 A B
1:    A    A 4 5
2:    A    B 4 7
3:    B    A 9 9
4:    B    B 4 3

dplyr中的逻辑相同

library(dplyr)
df1 %>%
  group_by(GRP1, GRP2) %>%
  summarise(A = median(A[!is.na(a)]), B = median(B[!is.na(b)]))

df1

df1 <- data.frame(
  GRP1 = c("A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "B"),
  GRP2 = c("A", "A", "A", "B", "B", "B", "A", "A", "A", "B", "B", "B"),
  A = c(0, 4, 6, 7, 0, 1, 9, 0, 0, 8, 3, 4),
  B = c(6, 0, 4, 8, 6, 7, 0, 9, 9, 7, 3, 0),
  a = c(1, 4, 7, 3, NA, 3, 7, NA, NA, 4, 8, 1),
  b = c(5, NA, 7, 9, 5, 6, NA, 8, 1, 7, 2, 9)
)

【讨论】:

    【解决方案2】:

    dplyr:

    library(dplyr)
    df1 %>% 
      mutate(A = ifelse(is.na(a), NA, A),
             B = ifelse(is.na(b), NA, B)) %>% 
    # I use this to put as NA the values we don't want to include
      group_by(GRP1, GRP2) %>% 
      summarise(A = median(A, na.rm = T),
                B = median(B, na.rm = T))
    
    # A tibble: 4 x 4
    # Groups:   GRP1 [?]
      GRP1  GRP2      A     B
      <fct> <fct> <dbl> <dbl>
    1 A     A         4     5
    2 A     B         4     7
    3 B     A         9     9
    4 B     B         4     3
    

    【讨论】:

      猜你喜欢
      • 2018-12-26
      • 2019-11-11
      • 2023-03-15
      • 2019-04-17
      • 1970-01-01
      • 1970-01-01
      • 2020-11-16
      • 1970-01-01
      • 2019-03-09
      相关资源
      最近更新 更多