R 如何从数据帧中的多个列中查找最频繁的值

R 如何从数据帧中的多个列中查找最频繁的值,r,dataframe,R,Dataframe,我的数据框架如下: S A B C D E 1 N N N N N 2 N Y Y N N 3 Y N Y N N 4 Y N Y Y Y 我需要在哪里创建一个新的F列,其中包含多个a、B、C、D和E列中出现次数最多的字符 输出应如下所示: S A B C D E F 1 N N N N N N 2 N Y Y N N N 3 Y N Y N N N 4 Y N Y Y Y Y 我们可以创建一个模式函数并应用于行 df1$F <- apply(df1[-1], 1, Mod

我的数据框架如下:

S A B C D E 
1 N N N N N
2 N Y Y N N
3 Y N Y N N
4 Y N Y Y Y
我需要在哪里创建一个新的F列,其中包含多个a、B、C、D和E列中出现次数最多的字符

输出应如下所示:

 S A B C D E F
 1 N N N N N N
 2 N Y Y N N N
 3 Y N Y N N N
 4 Y N Y Y Y Y

我们可以创建一个
模式
函数并应用于行

df1$F <- apply(df1[-1], 1, Mode)
df1
#  S A B C D E F
#1 1 N N N N N N
#2 2 N Y Y N N N
#3 3 Y N Y N N N
#4 4 Y N Y Y Y Y

或者另一种选择是

df1$F <- c('N', 'Y')[max.col(table(c(row(df1[-1])), unlist(df1[-1])), 'first')]
gather(df1, key, F, - S) %>% 
     group_by(S, F) %>% 
     summarise(n = n()) %>% 
     slice(which.max(n)) %>% 
     ungroup %>% 
     dplyr::select(F) %>% 
     bind_cols(df1, .)

或者我们转置数据集,按每列应用
模式
,然后将输出作为新列绑定到原始数据集

t(df1[-1]) %>%
   as.data.frame %>% 
   summarise_all(Mode) %>% 
   unlist %>%
   bind_cols(df1, F = .)

或带有
data.table的选项

library(data.table)
setDT(df1)[,  F := names(which.max(table(unlist(.SD)))), S][]
注意:这些是常规方法,而不是仅检查单个案例


如果我们需要一种有效的方法,而不需要任何
ifelse
,我们也可以通过

df1$F <- c("Y", "N")[(rowSums(df1[-1] == "N") > 2) + 1]
df1$F
#[1] "N" "N" "N" "Y"
或者另一种方法是

c("Y", "N")[(str_count(do.call(paste0, df1[-1]), "N") > 2) + 1]
数据
df1一个
dplyr
可能性可能是:

df %>%
 mutate(F = ifelse(rowSums(.[2:length(.)] == "N") > 2, "N", "Y"))

  S A B C D E F
1 1 N N N N N N
2 2 N Y Y N N N
3 3 Y N Y N N N
4 4 Y N Y Y Y Y
它假定只有
N
Y
值,列数为5

正如@Sotos所指出的,它可以很容易地重写为
base R
形式:

df$F <- ifelse(rowSums(df[2:length(df)] == "N") > 2, "N", "Y")
与基本R相同:

df$F <- ifelse(rowMeans(df[2:length(df)] == "N") > 0.5, "N", "Y")
df$F 0.5,“N”,“Y”)

另一种选择,略有不同:

x$F或:


d+1好主意,避免使用
apply()
1
。如果您不只是为管道加载
dplyr
,并且
mutate
,情况可能会好得多。只需将其保留在base R中。此外,还可以使
2
动态。类似于
天花(ncol(df)/2)
您可以使用rowMeans(…)>0.5来避免对列数进行假设
df1 <- structure(list(S = 1:4, A = c("N", "N", "Y", "Y"), B = c("N", 
"Y", "N", "N"), C = c("N", "Y", "Y", "Y"), D = c("N", "N", "N", 
"Y"), E = c("N", "N", "N", "Y")), class = "data.frame", row.names = c(NA, 
-4L))
df %>%
 mutate(F = ifelse(rowSums(.[2:length(.)] == "N") > 2, "N", "Y"))

  S A B C D E F
1 1 N N N N N N
2 2 N Y Y N N N
3 3 Y N Y N N N
4 4 Y N Y Y Y Y
df$F <- ifelse(rowSums(df[2:length(df)] == "N") > 2, "N", "Y")
df %>%
 mutate(F = ifelse(rowMeans(.[2:length(.)] == "N") > 0.5, "N", "Y"))
df$F <- ifelse(rowMeans(df[2:length(df)] == "N") > 0.5, "N", "Y")
d <- read.table(text ="S A B C D E 
1 N N N N N
2 N Y Y N N
3 Y N Y N N
4 Y N Y Y Y", header = TRUE, row.names = 1, stringsAsFactors = FALSE)

d$F <- with(
  stack(data.frame(t(as.matrix(d)), stringsAsFactors = FALSE)),
  tapply(values, ind, function(x) names(sort(table(x), decreasing = TRUE)[1])))
d

#A B C D E F
#1 N N N N N N
#2 N Y Y N N N
#3 Y N Y N N N
#4 Y N Y Y Y Y