2015-10-13 61 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