簡體   English   中英

使用`dplyr`避免`for`循環:計算到觀測值的距離

[英]Use `dplyr` to avoid `for` loop: calculate distance to observations

我有兩個數據集AB以及用於在每個觀測A我要計算的距離distance (例如,歐幾里德距離,L1距離,或其他內容),以在每個觀測B (該距離的計算是基於所述變量在數據集中)。 然后,來自A的觀測值應與B中距離最小的觀測值相關。

例如,如果A有5000個觀測值,而B有10000個觀測值,則

for(i in 1:5000)
{
     x = data.frame(x = numeric(), y = numeric())

     for(j in 1:10000)
     {
         x[j,] = distance(A[i,], B[j,])
     }

     A[i,]$associated_row_B = x[which.min(x[1,]),1]
}

基本上可以滿足我的要求(如果觀察距離相同,我仍然必須解決)。 但是由於我使用的是dplyr所以幾乎dplyr使用for循環。 我的解決方案甚至需要兩個循環,所以我想知道是否有可能使用dplyr / tidyverse提供的解決方案來避免for循環。

一個非常基本的例子:

A:

i           a b
1 -0.5920377 a
2  0.4263199 b
3  0.6737029 a
4  1.3063658 c
5  0.1314103 d

B:

i           a b
1 -0.30201541 a
2 -0.07093386 b
3  0.96317764 c
4 -0.33303061 d
5 -1.00834895 d

和距離函數:

distance = function(x,y) return(c((x[2] - y[2])^2 + abs(x[3] - y[3]), y[1])

返回值的第一個元素是實際距離,第二個值是來自B的標識符。

公平的警告:對於大型數據集,這將是非常低效的!

你可以做到這一點使用crossingtidyrslicedplyr

首先,讓我們創建兩個虛擬數據幀A_dfB_df

A_df <- data.frame(
  observation_A = runif(100),
  id_A = 1:100
)

B_df <- data.frame(
  observation_B = runif(50),
  id_B = 1:50
)

為了清楚起見,我在A_dfB_df之間保留了唯一的列名。 接下來,我們將使用tidyr::crossing查找兩個數據幀之間的行的每種組合。 接下來,我們使用mutate來計算距離(在這里,我任意取了它們的差的絕對值,但是您可以在此處應用自定義距離函數)。 最后,我們將id_A ,並使用slice保留最小值(並以R為which.max )。

library(tidyverse)


full_df <- A_df %>% 
  crossing(B_df) %>% 
  mutate(distance = abs(observation_A-observation_B)) %>% 
  group_by(id_A) %>% 
  slice(which.min(distance))

查看full_df ,我們得到了希望的結果:

> full_df
# A tibble: 100 x 5
# Groups:   id_A [100]
   observation_A  id_A observation_B  id_B distance
           <dbl> <int>         <dbl> <int>    <dbl>
 1         0.826     1         0.851    44  0.0251 
 2         0.903     2         0.905     3  0.00176
 3         0.371     3         0.368    18  0.00305
 4         0.554     4         0.577    34  0.0232 
 5         0.656     5         0.654    10  0.00268
 6         0.120     6         0.110    37  0.0101 
 7         0.991     7         0.988     6  0.00244
 8         0.983     8         0.988     6  0.00483
 9         0.325     9         0.318    45  0.00649
10         0.860    10         0.864    40  0.00407
# ... with 90 more rows

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM