【问题标题】:How to iterate over all combinations of two function arguments and return an 'n by m' matrix in r如何迭代两个函数参数的所有组合并在 r 中返回一个“n x m”矩阵
【发布时间】: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) %&gt;% count(value, key) %&gt;% spread(key, n, fill = 0)

标签: r functional-programming purrr


【解决方案1】:

@markus 提到的更短的基本 R 选项是使用 stack

table(stack(df))

使用sapply 的基本R 方法是使用table 根据列可以采用的最大值(数据框中的列号)指定levels 来计算每列的频率。

n <- ncol(df)
sapply(df, function(x) table(factor(x, levels = 1:n)))


#  A B C D E
#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

使用purrr 我们可以做到

purrr::map_dfr(df,~table(factor(., levels = 1:n)))

# 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

【讨论】:

  • 另一个baseR 选项是table(stack(results))
  • 这确实是一个方便的功能。您可以将此选项包含在您的答案中。
  • 感谢所有这些建议都很棒!我肯定是以一种非常复杂的方式来解决这个问题
猜你喜欢
  • 2020-06-18
  • 2012-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多