2015-10-13 16 views
1

我有一个真正的值(位置)的数据集,我试图用dplyr与估计值的向量进行比较。我的下面的代码导致错误消息。如何将每个数据$ location的值与est.locations的每个值进行比较,并在所有比较大于20时将结果向量折叠为真?dplyr :: 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 = (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链。 (即多次重复的地点数量将数据集之间和每个迭代不同。)

UPDATE(15年10月13日):

我会标记为答案akrun的解决方案。线性代数方法很适合这个问题,只需稍作调整就可以同时计算FNR和FPR(FNR应该需要(1)迭代应用,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 ] 
+0

数据的nrow与est.locations的长度不一样。如果你想做比较,也许'apply(外部(df1 $ location,est.location,FUN =' - ')> 20,2,any)' – akrun

+1

'est.locations < - runif(12,0,1500 )%>%sort'应该是'10'而不是'12' – Mateusz1981

+0

“真实”值的数目通常与数字“估计”值不同。比较是数据$ location的每个值与est.location的所有值之间的差异 - 如果任何值为TRUE,则结果应该是单个值= TRUE。 –

回答

0

我们可以使用outer对于这种比较。我们得到'location'和'est.locations'之差的所有组合,取abs,与20进行比较,否定(!),执行rowSums并再次取反,以便如果行中的所有元素都大于20 ,它将是真实的。

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