我有一个如下所示的数据框:
week_0 <- c(5,0,1,0,0,1)
week_1 <- c(5,0,4,0,2,1)
week_2 <- c(5,0,4,0,8,1)
week_3 <- c(5,0,4,0,8,3)
week_4 <- c(1,0,4,0,8,3)
week_5 <- c(1,0,4,0,8,3)
week_6 <- c(1,0,4,0,1,3)
week_7 <- c(1,0,4,0,1,3)
week_8 <- c(1,0,6,0,3,4)
week_9 <- c(2,4,6,7,3,4)
week_10 <- c(2,4,6,7,3,4)
Participant <- c("Lion","Cat","Dog","Snake","Tiger","Mouse")
test_data <- data.frame(Participant,week_0,week_1,week_2,week_3,week_4,week_5,week_6,week_7,week_8,week_9,week_10)
> test_data
Participant week_0 week_1 week_2 week_3 week_4 week_5 week_6 week_7 week_8 week_9 week_10
1 Lion 5 5 5 5 1 1 1 1 1 2 2
2 Cat 0 0 0 0 0 0 0 0 0 4 4
3 Dog 1 4 4 4 4 4 4 4 6 6 6
4 Snake 0 0 0 0 0 0 0 0 0 7 7
5 Tiger 0 2 8 8 8 8 1 1 3 3 3
6 Mouse 1 1 1 3 3 3 3 3 4 4 4
我想找出一行中比其他值出现更多的值。例如,对于第一行,值为 1。对于第一行,我要返回的输出是
week_4
。对于第二行,出现次数多于其他的值是0。我要返回的输出是week_0
,等等。所以最终结果应该是:
week_4
,week_0
,week_1
,week_0
,week_2
,week_3
。我必须使用:
apply(test_data, 1, function(x) names(which.max(table(x))))
但是我没有得到我正在搜索的结果。关于如何做到这一点有什么建议吗?
您的代码是良好的开端。您可以使用结果
match()
它在行中的第一个位置,然后使用这个位置索引到列名中:
apply(test_data[, -1], 1, function(x) {
val <- names(which.max(table(x)))
names(test_data)[-1][[match(val, x)]]
})
# "week_4" "week_0" "week_1" "week_0" "week_2" "week_3"
注意我用
test_data[, -1]
排除Participant
列;否则,如果没有多次出现的值,代码将返回参与者姓名,这可能不是您想要的。
dplyr
解决方案 add_count
+ slice_max
:
library(dplyr)
test_data %>%
tidyr::pivot_longer(starts_with('week')) %>%
add_count(Participant, value) %>%
slice_max(n, by = Participant, with_ties = FALSE)
# # A tibble: 6 × 4
# Participant name value n
# <chr> <chr> <dbl> <int>
# 1 Lion week_4 1 5
# 2 Cat week_0 0 9
# 3 Dog week_1 4 7
# 4 Snake week_0 0 9
# 5 Tiger week_2 8 4
# 6 Mouse week_3 3 5
如果有“领带”并且您想在输出中包含所有领带:
test_data %>%
tidyr::pivot_longer(starts_with('week')) %>%
add_count(Participant, value) %>%
slice_max(n, by = c(Participant, value), with_ties = FALSE) %>%
slice_max(n, by = Participant)
首先定义一个函数来查找向量的模式:
Mode <- \(x) names(sort(-table(x)))[1]
困难的部分已经完成。现在使用 dplyr 的
rowwise()
和 c_across()
:
library(dplyr)
test_data %>%
rowwise() %>%
mutate(
m = {
x <- c_across(week_0:week_10) # get row as a vector
names(x) <- names(test_data)[-1]
index <- which(x == Mode(x))[1] # first occurence of mode in 'x'
names(x)[index]
}
)
尝试
fmode
来自collapse
library(collapse)
names(test_data)[-1][max.col(test_data[-1] == dapply(test_data[-1],
MARGIN = 1, fmode), "first")]
-输出
[1] "week_4" "week_0" "week_1" "week_0" "week_2" "week_3"