【发布时间】:2019-08-08 18:45:42
【问题描述】:
我想计算候选人在(随机生成的)选举中收到的第一、第二、第三等偏好的数量:
library(tidyverse)
library(magrittr)
set.seed(42)
results <- replicate(10, sample.int(5,5)) %>%
t() %>%
tbl_df() %>%
set_colnames(c("A", "B", "C", "D", "E"))
# A tibble: 10 x 5
A B C D E
<int> <int> <int> <int> <int>
1 5 4 1 2 3
2 3 5 1 2 4
3 3 5 4 1 2
4 5 4 1 3 2
5 5 1 3 2 4
6 3 2 5 1 4
7 4 5 2 3 1
8 5 1 4 2 3
9 2 5 1 4 3
10 5 4 2 3 1
我的功能是:
count_prefs <- function(df, candidate, round) {
df %>%
filter_at(vars(candidate), all_vars(. == round)) %>%
nrow()
}
我想要的输出是一个“n x m”表,其中 n 是候选数,m 是轮数(我意识到在这种情况下 n = m,但我也想更普遍地解决这个问题) .我试过了:
map2_dbl(colnames(results), c(1:5), count_prefs, df = results)
但它会返回
[1] 0 1 1 1 0
这只是“A 1”“B 2”“C 3”“D 4”“E 5”。
到目前为止,我的解决方案是使用 cross2() 获取所有组合的列表并应用同一函数的调整版本:
count_prefs2 <- function(df, cand_round) {
df %>%
filter_at(vars(cand_round[[1]]), all_vars(. == cand_round[[2]])) %>%
nrow()
}
map_int(cross2(colnames(results), c(1:5)), count_prefs2, df = results)
[1] 0 2 4 2 2 1 1 2 4 2 3 0 1 3 3 1 3 2 1 3 5 4 1 0 0
这给了我正确的数字,但我需要将其转换为矩阵,然后转换为数据框以获得我想要的结果
map_int(cross2(colnames(results), c(1:5)), count_prefs2, df = results) %>%
matrix(nrow = 5, ncol = 5, byrow = TRUE) %>%
tbl_df() %>%
set_colnames(c("A", "B", "C", "D", "E"))
# A tibble: 5 x 5
A B C D E
<int> <int> <int> <int> <int>
1 0 2 4 2 2
2 1 1 2 4 2
3 3 0 1 3 3
4 1 3 2 1 3
5 5 4 1 0 0
这个问题有更优雅的解决方案吗?
【问题讨论】:
-
一个tidyverse方式是
gather(results) %>% count(value, key) %>% spread(key, n, fill = 0)
标签: r functional-programming purrr