从多列数据框中检索最大值

时间:2019-04-16 14:31:16

标签: r

我有一个如下所示的数据集

Account eta1    eta2    eta3    eta4    eta6  grp  grp1
123       NA    0      0       1       NA     pol  tree
456       NA    NA     NA      NA       1     cal  tre
789       NA    NA     NA      0        2     pal   tre
111       NA    NA     NA      NA      NA     trol  tre

我希望我的输出看起来像这样

ACC  eta  grp grp1
123   1  pol  tree
456   1  cal  tre
789   2  pal   tre
111  NA  trol  tre

我如何使用R实现这一目标

4 个答案:

答案 0 :(得分:4)

尝试一下:

df<-structure(list(Account = c(123L, 456L, 789L, 111L), eta1 = c(NA, 
NA, NA, NA), eta2 = c(0L, NA, NA, NA), eta3 = c(0L, NA, NA, NA
), eta4 = c(1L, NA, 0L, NA), eta6 = c(NA, 1L, 2L, NA), grp = c("pol", 
"cal", "pal", "trol"), grp1 = c("tree", "tre", "tre", "tre")), class = "data.frame", row.names = c(NA, 
-4L))

数据

.example {
  width: 400px;
  height: 90vh;
  background-color: red;
  border: 1px solid black;
}

答案 1 :(得分:2)

另一种方法是使用dplyr

library(dplyr)

df <- data.frame(stringsAsFactors = FALSE,
                 Account = c(123, 456, 789, 111),
                 eta1 = c(NA, NA, NA, NA),
                 eta2 = c(0, NA, NA, NA),
                 eta3 = c(0, NA, NA, NA),
                 eta4 = c(1, NA, 0, NA),
                 eta6 = c(NA, 1, 2, NA),
                 grp = c("pol", "cal", "pal", "trol"),
                 grp1 = c("tree", "tre", "tre", "tre"))

df %>%
  mutate(eta = pmax(eta1, eta2, eta3, eta4, eta6, na.rm = TRUE)) %>%
  select(Account, eta, grp, grp1)

答案 2 :(得分:0)

在数字列上应用max,但有例外规则。 (但是 @nicola 的解决方案更好。)

apply(dat[sapply(dat, is.numeric)], 1, 
      function(x) if (all(is.na(x))) NA else max(na.omit(x)))
# [1]  2  1  2 NA

您可以将其进一步包装到自定义函数中

row.max <- function(dat) {
  return(apply(dat[sapply(dat, is.numeric)], 1, 
        function(x) if (all(is.na(x))) NA else max(na.omit(x))))
}

用法:

dat <- transform(dat, max=row.max(dat))
#   Account eta1 eta2 eta3 eta4 eta6  grp grp1 max
# 1     123   NA    1    1    2   NA  pol tree   2
# 2     456   NA   NA   NA   NA    1  cal  tre   1
# 3     789   NA   NA   NA    1    2  pal  tre   2
# 4     111   NA   NA   NA   NA   NA trol  tre  NA

数据

dat <- structure(list(Account = structure(c(2L, 3L, 4L, 1L), .Label = c("111", 
"123", "456", "789", "Account"), class = "factor"), eta1 = c(NA_real_, 
NA_real_, NA_real_, NA_real_), eta2 = c(1, NA, NA, NA), eta3 = c(1, 
NA, NA, NA), eta4 = c(2, NA, 1, NA), eta6 = c(NA, 1, 2, NA), 
    grp = structure(c(4L, 1L, 3L, 5L), .Label = c("cal", "grp", 
    "pal", "pol", "trol"), class = "factor"), grp1 = structure(c(3L, 
    2L, 2L, 2L), .Label = c("grp1", "tre", "tree"), class = "factor")), row.names = c(NA, 
-4L), class = "data.frame")

答案 3 :(得分:0)

我喜欢使用dplyrtidyr处理类似的问题,特别是将数据重塑为可扩展的形式。通常,我更喜欢将ETA变量放在一列中,而不是在eta1eta2等上进行操作,因此我不会遗漏任何东西,因此我的工作足够灵活以添加或删除列。

就像其他人提到的那样,棘手的部分即使在所有值均为NA的情况下也获得了最大值。我编写了一个函数来处理此问题,如果所有值均为NA,则返回NA

library(dplyr)
library(tidyr)

max_or_na <- function(x) {
  if (all(is.na(x))) {
    NA
  } else {
    max(x, na.rm = T)
  }
}

df %>%
  gather(key = eta, value, starts_with("eta")) %>%
  group_by(Account, grp, grp1) %>%
  summarise(eta = max_or_na(value))
#> # A tibble: 4 x 4
#> # Groups:   Account, grp [4]
#>   Account grp   grp1    eta
#>     <int> <chr> <chr> <int>
#> 1     111 trol  tre      NA
#> 2     123 pol   tree      1
#> 3     456 cal   tre       1
#> 4     789 pal   tre       2

然后,您可以根据需要取消分组和重新排序。