在一行中查找所有绑定的最大值,如果列包含最大值,则返回true或false

时间:2019-07-22 09:16:21

标签: r

我有一些包含数字列的数据:

df <- data.frame(v1 = c(0,1,2,3,4,5,6,7,8,9),
                 v2 = c(2,1,4,7,6,7,8,9,0,1),
                 v3 = c(4,1,6,7,8,9,0,1,2,3),
                 v4 = c(0,1,2,7,4,5,6,7,8,9),
                 v5 = c(0,1,6,3,6,9,8,9,0,1))

我可以找到第一个最大值,并使用which.max返回其列名:

df$max <- colnames(df)[apply(df,1,which.max)]

相反,我想添加五个新列,如果对应的列是最大值或最大值,则插入TRUE,否则插入FALSE:

   v1 v2 v3 v4 v5 v1max v2max v3max v4max v5max
1   0  2  4  0  0 FALSE FALSE TRUE  FALSE FALSE
2   1  1  1  1  1 TRUE  TRUE  TRUE  TRUE  TRUE  
3   2  4  6  2  6 FALSE FALSE TRUE  FALSE TRUE     
4   3  7  7  7  3 FALSE TRUE  TRUE  TRUE  FALSE
5   4  6  8  4  6 FALSE FALSE TRUE  FALSE FALSE
6   5  7  9  5  9 FALSE FALSE TRUE  FALSE TRUE
7   6  8  0  6  8 FALSE TRUE  FALSE FALSE TRUE
8   7  9  1  7  9 FALSE TRUE  FALSE FALSE TRUE
9   8  0  2  8  0 TRUE  FALSE FALSE TRUE  FALSE
10  9  1  3  9  1 TRUE  FALSE FALSE TRUE  FALSE

有没有简单的方法可以实现这一目标?

5 个答案:

答案 0 :(得分:4)

一种简单有效的解决方案是使用do.callpmax获得按行最大值,并将其与数据帧进行比较,以获得可以分配为新列的逻辑向量。

df[paste0(names(df), "max")] <- df == do.call(pmax, df)

df
#   v1 v2 v3 v4 v5 v1max v2max v3max v4max v5max
#1   0  2  4  0  0 FALSE FALSE  TRUE FALSE FALSE
#2   1  1  1  1  1  TRUE  TRUE  TRUE  TRUE  TRUE
#3   2  4  6  2  6 FALSE FALSE  TRUE FALSE  TRUE
#4   3  7  7  7  3 FALSE  TRUE  TRUE  TRUE FALSE
#5   4  6  8  4  6 FALSE FALSE  TRUE FALSE FALSE
#6   5  7  9  5  9 FALSE FALSE  TRUE FALSE  TRUE
#7   6  8  0  6  8 FALSE  TRUE FALSE FALSE  TRUE
#8   7  9  1  7  9 FALSE  TRUE FALSE FALSE  TRUE
#9   8  0  2  8  0  TRUE FALSE FALSE  TRUE FALSE
#10  9  1  3  9  1  TRUE FALSE FALSE  TRUE FALSE

使用apply的解决方案可能是

df[paste0(names(df), "max")] <- t(apply(df, 1, function(x) x == max(x)))

答案 1 :(得分:2)

写一个辅助功能is.maxapply逐行写入df

is.max <- function(x, na.rm = TRUE){
  x == max(x, na.rm = na.rm)
}

res <- t(apply(df, 1, is.max))
colnames(res) <- paste(colnames(res), "max", sep = ".")
res <- cbind(df, res)

res
#   v1 v2 v3 v4 v5 v1.max v2.max v3.max v4.max v5.max
#1   0  2  4  0  0  FALSE  FALSE   TRUE  FALSE  FALSE
#2   1  1  1  1  1   TRUE   TRUE   TRUE   TRUE   TRUE
#3   2  4  6  2  6  FALSE  FALSE   TRUE  FALSE   TRUE
#4   3  7  7  7  3  FALSE   TRUE   TRUE   TRUE  FALSE
#5   4  6  8  4  6  FALSE  FALSE   TRUE  FALSE  FALSE
#6   5  7  9  5  9  FALSE  FALSE   TRUE  FALSE   TRUE
#7   6  8  0  6  8  FALSE   TRUE  FALSE  FALSE   TRUE
#8   7  9  1  7  9  FALSE   TRUE  FALSE  FALSE   TRUE
#9   8  0  2  8  0   TRUE  FALSE  FALSE   TRUE  FALSE
#10  9  1  3  9  1   TRUE  FALSE  FALSE   TRUE  FALSE

答案 2 :(得分:2)

一个cbind()评估每一行到每一行的max()将会成功:

df2<-cbind(df,df == apply(df,1,max))
colnames(df2)<-c("v1", "v2" ,"v3", "v4" ,"v5", "v1max", "v2max", "v3max" ,"v4max", "v5max")
df2            
# v1 v2 v3 v4 v5 v1max v2max v3max v4max v5max
# 1   0  2  4  0  0 FALSE FALSE  TRUE FALSE FALSE
# 2   1  1  1  1  1  TRUE  TRUE  TRUE  TRUE  TRUE
# 3   2  4  6  2  6 FALSE FALSE  TRUE FALSE  TRUE
# 4   3  7  7  7  3 FALSE  TRUE  TRUE  TRUE FALSE
# 5   4  6  8  4  6 FALSE FALSE  TRUE FALSE FALSE
# 6   5  7  9  5  9 FALSE FALSE  TRUE FALSE  TRUE
# 7   6  8  0  6  8 FALSE  TRUE FALSE FALSE  TRUE
# 8   7  9  1  7  9 FALSE  TRUE FALSE FALSE  TRUE
# 9   8  0  2  8  0  TRUE FALSE FALSE  TRUE FALSE
# 10  9  1  3  9  1  TRUE FALSE FALSE  TRUE FALSE

答案 3 :(得分:2)

使用max.col

cbind(df, df==df[cbind( 1:nrow(df), max.col(df) )])

   # v1 v2 v3 v4 v5    v1    v2    v3    v4    v5
# 1   0  2  4  0  0 FALSE FALSE  TRUE FALSE FALSE
# 2   1  1  1  1  1  TRUE  TRUE  TRUE  TRUE  TRUE
# 3   2  4  6  2  6 FALSE FALSE  TRUE FALSE  TRUE
# 4   3  7  7  7  3 FALSE  TRUE  TRUE  TRUE FALSE
# 5   4  6  8  4  6 FALSE FALSE  TRUE FALSE FALSE
# 6   5  7  9  5  9 FALSE FALSE  TRUE FALSE  TRUE
# 7   6  8  0  6  8 FALSE  TRUE FALSE FALSE  TRUE
# 8   7  9  1  7  9 FALSE  TRUE FALSE FALSE  TRUE
# 9   8  0  2  8  0  TRUE FALSE FALSE  TRUE FALSE
# 10  9  1  3  9  1  TRUE FALSE FALSE  TRUE FALSE

答案 4 :(得分:1)

一种tidyverse可能是:

df %>%
 mutate_all(list(max = ~ . == exec(pmax, !!!.)))

   v1 v2 v3 v4 v5 v1_max v2_max v3_max v4_max v5_max
1   0  2  4  0  0  FALSE  FALSE   TRUE  FALSE  FALSE
2   1  1  1  1  1   TRUE   TRUE   TRUE   TRUE   TRUE
3   2  4  6  2  6  FALSE  FALSE   TRUE  FALSE   TRUE
4   3  7  7  7  3  FALSE   TRUE   TRUE   TRUE  FALSE
5   4  6  8  4  6  FALSE  FALSE   TRUE  FALSE  FALSE
6   5  7  9  5  9  FALSE  FALSE   TRUE  FALSE   TRUE
7   6  8  0  6  8  FALSE   TRUE  FALSE  FALSE   TRUE
8   7  9  1  7  9  FALSE   TRUE  FALSE  FALSE   TRUE
9   8  0  2  8  0   TRUE  FALSE  FALSE   TRUE  FALSE
10  9  1  3  9  1   TRUE  FALSE  FALSE   TRUE  FALSE