【问题标题】:dplyr::mutate comparing each value to vector, collapsing with any/alldplyr::mutate 将每个值与向量进行比较,与任何/全部折叠
【发布时间】:2015-10-13 06:49:51
【问题描述】:

我有一个真实值(位置)数据集,我试图将其与使用 dplyr 的估计值向量进行比较。我下面的代码会导致错误消息。如果所有比较都大于 20,如何将 data$location 的每个值与 est.locations 的每个值进行比较并将结果向量折叠为 true?

library(dplyr)
data <- data.frame("num" = 1:10, "location" = runif(10, 0, 1500) %>%   sort)
est.locations <- runif(12, 0, 1500) %>% sort

data %>% 
  mutate(false.neg = (all(abs(location - est.locations) > 20)))

   num  location false.neg
1    1  453.4281     FALSE
2    2  454.4260     FALSE
3    3  718.0420     FALSE
4    4  801.2217     FALSE
5    5  802.7981     FALSE
6    6  854.2148     FALSE
7    7  873.6085     FALSE
8    8  901.0217     FALSE
9    9 1032.8321     FALSE
10  10 1240.3547     FALSE
Warning message:
In c(...) :
  longer object length is not a multiple of shorter object length

问题的上下文是 dplyr,但我愿意接受其他可能更快的建议。这是我对 3000 次迭代 * 200 个数据集的生死 mcmc 链进行的更大计算的一部分。 (即重复多次,数据集之间和每次迭代的位置数量都会不同。)

更新(2015 年 10 月 13 日):

我会将 akrun 的解决方案标记为答案。线性代数方法很适合这个问题,稍微调整一下,这将适用于计算 FNR 和 FPR(FNR 应该需要 (l) 通过迭代应用,FPR 应该是一个大型向量/矩阵运算)。

JohannesNE 的解决方案指出了我最初方法的问题 - 使用 any() 将行数减少到单个值,而我打算按行执行此操作。这也让我认为可能有一个使用 rowwise() 和 do() 的 dplyr 解决方案。

我试图在我最初的帖子中限制问题的范围。但是为了增加上下文,完整的问题在于具有未知数量组件的贝叶斯混合模型,其中组件由一维点过程定义。估计会产生一个“随机效应”链,其结构类似于下面的 est.locations 版本。长度不匹配是必须估计组件数量的结果。

## Clarification of problem
options("max.print" = 100)
set.seed(1)

# True values (number of items and their location)
true.locations <- 
  data.frame("num"      = 1:10, 
             "location" = runif(10, 0, 1500) %>% sort)

# Mcmc chain of item-specific values ('random effects')
iteration <<- 0
est.locations <- 
  lapply(sample(10:14, 3000, replace=T), function(x) {
      iteration  <<- iteration + 1
      total.items <- rep(x, x)
      num         <- 1:x
      location    <- runif(x, 0, 1500) %>% sort
      data.frame(iteration, total.items, num, location)
    }) %>% do.call(rbind, .) 
print(est.locations)

      iteration total.items num      location
1             1          11   1   53.92243818
2             1          11   2  122.43662006
3             1          11   3  203.87297671
4             1          11   4  641.70211495
5             1          11   5  688.19477968
6             1          11   6 1055.40283048
7             1          11   7 1096.11595818
8             1          11   8 1210.26744065
9             1          11   9 1220.61185888
10            1          11  10 1362.16553219
11            1          11  11 1399.02227302
12            2          10   1  160.55916378
13            2          10   2  169.66834129
14            2          10   3  212.44257723
15            2          10   4  228.42561489
16            2          10   5  429.22830291
17            2          10   6  540.42659572
18            2          10   7  594.58339156
19            2          10   8  610.53964624
20            2          10   9  741.62600969
21            2          10  10  871.51458277
22            3          13   1   10.88957267
23            3          13   2   42.66629869
24            3          13   3  421.77297967
25            3          13   4  429.95036650
 [ reached getOption("max.print") -- omitted 35847 rows ]

【问题讨论】:

  • 数据的nrow与est.locations的长度不同。如果你想做比较,也许apply(outer(df1$location, est.location, FUN= '-') &gt; 20, 2, any)
  • est.locations &lt;- runif(12, 0, 1500) %&gt;% sort应该是10而不是12
  • “真实”值的数量经常与“估计”值的数量不同。比较的是 data$location 的每个值与 est.location 的所有值之间的差异——如果任何一个为 TRUE,那么结果应该是单个值 = TRUE。
  • 您真的要在 location 和 est.locations 之间的长度不匹配的情况下强制执行此回收吗?这似乎是一个错误。 @Mateusz1981 似乎是正确的,您的 runif(n...) 长度参数不匹配。
  • 我正在尝试进行 10、1 到 12 次比较,每次使用“全部”都会减少一个结果(总共 10 个值,每行“数据”一个)。早上我会再澄清一点。

标签: r dplyr


【解决方案1】:

您可以使用 sapply(这里是 mutate,但没有真正利用它的功能)。

library(dplyr)
data <- data.frame("num" = 1:10, "location" = runif(10, 0, 1500) %>%   sort)
est.locations <- runif(12, 0, 1500) %>% sort

data %>% 
    mutate(false.neg = sapply(location, function(x) {
        all(abs(x - est.locations) > 20)
    }))

   num   location false.neg
1    1   92.67941      TRUE
2    2  302.52290     FALSE
3    3  398.26299      TRUE
4    4  558.18585     FALSE
5    5  859.28005      TRUE
6    6  943.67107      TRUE
7    7  991.19669      TRUE
8    8 1347.58453      TRUE
9    9 1362.31168      TRUE
10  10 1417.01290     FALSE

【讨论】:

    【解决方案2】:

    我们可以使用outer 进行这种比较。我们得到'location'和'est.locations'之间差异的所有组合,取abs,与20比较,取反(!),做rowSums并再次取反,这样如果所有元素在行数大于 20,则为 TRUE。

    data$false.neg <- !rowSums(!abs(outer(data$location, est.locations, FUN='-'))>20) 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-15
      • 2021-12-29
      • 1970-01-01
      • 2015-01-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多