每行中的最大数量以及更多

时间:2015-04-16 18:40:43

标签: r

我的数据集包含四个数值变量X1,X2,X3,X_4和一个ID列。

ID <- c(1,2,3,4,5,6,7,8,9,10)
X1 <- c(3,1,1,1,2,1,2,1,3,4)
X2 <- c(1,2,1,3,2,2,4,1,2,4)
X3 <- c(1,1,1,3,2,3,3,2,1,4)
X4 <- c(1,4,1,1,1,4,3,1,4,4)
Mydata <- data.frame(ID, X1,X2,X3,X4)

我需要再创建两列:1)Max,和2)Var

1)最大列:对于每个只有一个最大值的行,我需要在Max变量中保存这个“max”值。如果是的话 row有多个,那么Max值应该是999。

2)Var列:对于只有一个最大值的行,我需要知道它是X1,X2,X3 $还是X4。

对于上述数据集,这是输出:

ID  X1  X2  X3  X4  Max Var
1   3   1   1   1   3   X1
2   1   2   1   4   4   X4
3   1   1   1   1   999 NA
4   1   3   3   1   999 NA
5   2   2   2   1   999 NA
6   1   2   3   4   4   X4
7   2   4   3   3   4   X2
8   1   1   2   1   2   X3
9   3   2   1   4   4   X4
10  4   4   4   4   999 NA

4 个答案:

答案 0 :(得分:7)

我们可以获得&#39; Mydata&#39;的列名。使用max.col(&#39; Var&#39;)获取每行中的最大值(不包括&#39; ID&#39;列),以及pmax的每行最大值( &#39;最大&#39)。为具有多个最大值(&#39; indx&#39;)的行创建逻辑索引,并将其与ifelse一起使用以获得预期的输出。

Var <- names(Mydata[-1])[max.col(Mydata[-1])]
Max <- do.call(pmax,Mydata[-1])
indx <- rowSums(Mydata[-1]==Max)>1

transform(Mydata, Var= ifelse(indx,  NA, Var), Max=ifelse(indx,  999, Max))

答案 1 :(得分:4)

这是另一种可能的apply解决方案

MyFunc <- function(x){
  Max <- max(x)
  if(sum(x == Max) > 1L) {
    Max <- 999
    Var <- NA     
    } else {
      Var <- which.max(x)
      }
  c(Max, Var)
}

Mydata[c("Max", "Var")] <- t(apply(Mydata[-1], 1, MyFunc))
#    ID X1 X2 X3 X4 Max Var
# 1   1  3  1  1  1   3   1
# 2   2  1  2  1  4   4   4
# 3   3  1  1  1  1 999  NA
# 4   4  1  3  3  1 999  NA
# 5   5  2  2  2  1 999  NA
# 6   6  1  2  3  4   4   4
# 7   7  2  4  3  3   4   2
# 8   8  1  1  2  1   2   3
# 9   9  3  2  1  4   4   4
# 10 10  4  4  4  4 999  NA

答案 2 :(得分:3)

我会将其分解为一些小步骤,这可能不是最有效的,但至少会给你一个起点,如果效率是你真正问题的问题。

首先,计算行maxes:

maxs <- apply(Mydata[, -1], 1, max)

> maxs
 [1] 3 4 1 3 2 4 4 2 4 4

接下来计算行中哪些值等于最大值

wMax <- apply(Mydata[, -1], 1, function(x) length(which(x == max(x))))

这给出了一个列表,我们可以sapply()结束以获得等于最大值的值的数量:

nMax <- sapply(wMax, length)

> nMax
 [1] 1 1 4 2 3 1 1 1 1 4

现在添加Max&amp; Var列:

Mydata$Max <- ifelse(nMax > 1L, 999, maxs)
Mydata$Var <- ifelse(nMax > 1L, NA, sapply(wMax, `[[`, 1))

> Mydata
   ID X1 X2 X3 X4 Max Var
1   1  3  1  1  1   3   1
2   2  1  2  1  4   4   4
3   3  1  1  1  1 999  NA
4   4  1  3  3  1 999  NA
5   5  2  2  2  1 999  NA
6   6  1  2  3  4   4   4
7   7  2  4  3  3   4   2
8   8  1  1  2  1   2   3
9   9  3  2  1  4   4   4
10 10  4  4  4  4 999  NA

这不会赢得任何奖项以优雅使用该语言,但它可以工作,你可以建立它。

(创建Var的最后一行需要一些解释:wMax实际上是一个列表。我们想要该列表中每个组件的第一个元素(因为那些将是唯一的最大值),并且sapply()调用产生了这个。)

现在我们可以编写一个包含所有步骤的函数:

MaxVar <- function(x, na.rm = FALSE) {
  ## compute `max`
  maxx <- max(x, na.rm = na.rm)
  ## which equal the max
  wmax <- which(x == max(x))
  ## how many equal the max
  nmax <- length(wmax)
  ## return
  out <- if(nmax > 1L) {
    c(999, NA)
  } else {
    c(maxx, wmax)
  }
  out
}

并像这样使用它:

> new <- apply(Mydata[, -1], 1, MaxVar)
> new
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]    3    4  999  999  999    4    4    2    4   999
[2,]    1    4   NA   NA   NA    4    2    3    4    NA
> Mydata <- cbind(Mydata, Max = new[1, ], Var = new[2, ])
> Mydata
   ID X1 X2 X3 X4 Max Var
1   1  3  1  1  1   3   1
2   2  1  2  1  4   4   4
3   3  1  1  1  1 999  NA
4   4  1  3  3  1 999  NA
5   5  2  2  2  1 999  NA
6   6  1  2  3  4   4   4
7   7  2  4  3  3   4   2
8   8  1  1  2  1   2   3
9   9  3  2  1  4   4   4
10 10  4  4  4  4 999  NA

同样,不是最优雅或最有效的代码,但它有效并且很容易看到它正在做什么。

答案 3 :(得分:0)

使用apply

执行此操作的另一种方法
Mydata$Max = apply(Mydata[,-1], 1,
function(x){ m = max(x); ifelse(m !=  max(x[duplicated(x)]), m, 999)})

Mydata$Var = apply(Mydata[,-1], 1, 
function(x){ index = which.max(x); ifelse(index != 5, names(x)[index], NA)})

#> Mydata
#ID X1 X2 X3 X4 Max  Var
#1   1  3  1  1  1   3   X1
#2   2  1  2  1  4   4   X4
#3   3  1  1  1  1 999 <NA>
#4   4  1  3  3  1 999 <NA>
#5   5  2  2  2  1 999 <NA>
#6   6  1  2  3  4   4   X4
#7   7  2  4  3  3   4   X2
#8   8  1  1  2  1   2   X3
#9   9  3  2  1  4   4   X4
#10 10  4  4  4  4 999 <NA>