[英]How to find the most frequent value from multiple columns in a 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
我們可以創建一個Mode
函數並應用於行
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')]
哪里
Mode <- function(x) {
ux <- unique(x)
ux[which.max(tabulate(match(x, ux)))]
}
或者使用tidyverse
library(tidyverse)
df1 %>%
mutate(F = pmap_chr(.[-1], ~ Mode(c(...))))
或者另一個選擇是
gather(df1, key, F, - S) %>%
group_by(S, F) %>%
summarise(n = n()) %>%
slice(which.max(n)) %>%
ungroup %>%
dplyr::select(F) %>%
bind_cols(df1, .)
或者我們轉置數據集,按每列應用Mode
,然后將輸出作為新列綁定到原始數據集
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"
或者使用Reduce
c("Y", "N")[(Reduce(`+`, lapply(df1[-1], `==`, "N")) > 2) + 1]
或者另一種方法是
c("Y", "N")[(str_count(do.call(paste0, df1[-1]), "N") > 2) + 1]
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))
一個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")
或者沒有關於列數的假設(基於@TinglTanglBob):
df %>%
mutate(F = ifelse(rowMeans(.[2:length(.)] == "N") > 0.5, "N", "Y"))
與基數R相同:
df$F <- ifelse(rowMeans(df[2:length(df)] == "N") > 0.5, "N", "Y")
一個替代方案,略有不同:
x$F <- unlist(do.call(Map, c(function(...) names(sort(-table(c(...)), partial=1)[1]), x[,-1])))
x
# 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
也許我現在只是想制作模糊的代碼......
我意識到這可能比絕對必要更普遍。 無論行之間存在多少不同的東西,這都會找到最常見的“事物”。
sort(..., partial=1)
在第一次傳遞后停止排序。
要么:
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.