Вычислить расстояние между вектором координат в 1 df и одиночными координатами в другом df - PullRequest
0 голосов
/ 06 февраля 2020

Предположим, у меня есть следующие два кадра данных (с неровными строками)

set.seed(1999)
dfA <- data.frame(x = rpois(10,2), y = rpois(10,2), z = rpois(10,2), q = rpois(10,2), t = rpois(10,2))

set.seed(24)
dfB <- data.frame(a = rpois(10,2), b = rpois(10,2), c = rpois(10,2), d = rpois(10,2), e = rpois(10,2))

set.seed(10)
Dx <- sample.int(5)
set.seed(6)
Dy <- sample.int(5)

Dx <- as.data.frame(Dx)
Dx <- as.data.frame(transpose(Dx))
Dy <- as.data.frame(Dy)
Dy <- as.data.frame(transpose(Dy))

dfAB <- map2_df(dfA, dfB, str_c, sep=",") %>%
  rename_all(~ str_c('C', seq_along(.)))
dfXY <- map2_df(Dx, Dy, str_c, sep=",") %>%
  rename_all(~ str_c('C', seq_along(.)))

Теперь у меня есть 2 набора данных координат (dfAB 5 переменных каждая с 10 наблюдениями, набор данных dfXY 5 переменных с 1 наблюдением).

Что мне хотелось бы, так это новый кадр данных с расстоянием между наблюдением переменной 1 dfXY и каждым отдельным наблюдением в переменной 1 dfAB, расстоянием между наблюдением 1 переменной 2 dfXY и каждым отдельным наблюдением в переменной 2 из dfAB, et c.

Если у нас есть

dfAB                          dfXY
3,1   3,2  ...       3,5  1,2  2,1  5,4  4,3   
2,1   3,1                  
2,3   1,2               
...   ...            

, то новый фрейм данных должен содержать расстояние между: a) 3,5 и 3,1 b) 3, 5 & ​​2,1 c) 3,5 & 2,3 et c ...
и расстояние между: а) 1,2 и 3,2 б) 1,2 и 3,1 c) 1,2 & 1,2 et c ..
и т. Д. С желаемым форматом вывода:

     dfABXY
C1:        C2:        C3:        C4:         C5 etc...
4.000000   2.000000   1.000000   3.605551
4.123106   2.236068   1.414214   3.605551              
2.236068   0.000000   2.236068   4.242641
3.162278   0.000000   1.000000   3.605551
3.162278   1.414214   2.000000   2.000000
etc...     etc...     etc...     etc...

Однако, когда я использую:

distances <- map2_df(
  dfAB,
  dfXY,
  ~ sqrt((.x$x - .y$x)^2 + (.x$y - .y$y)^2)
)

Я получаю ошибку Error in .x$x : $ operator is invalid for atomic vectors

Я думаю, что мне нужно использовать что-то вроде for(i in seq_along()) функции, но я не знаю, как включить * 10 23 *

distance <- for(i in seq_along(dfXY)){
  dfAB[,i] <- dfAB[,i] [WHAT TO PUT HERE]

Обратите внимание, что мой фактический набор данных - это тысячи строк и столбцов, поэтому я вызываю строки / столбцы вручную, нежизнеспособно.

Любая помощь приветствуется

1 Ответ

1 голос
/ 06 февраля 2020

работая с предоставленными образцами данных, я пришел к этому data.table -подходу

library( data.table )
#set as data.tables
setDT(dfAB)
setDT(dfXY)
#melt to long format
dt1 <- melt( dfAB, measure.vars = names(dfAB) )[, c("x_AB","y_AB") := lapply( tstrsplit( value, ","), as.numeric ) ]
dt2 <- melt( dfXY, measure.vars = names(dfXY) )[, c("x_XY","y_XY") := lapply( tstrsplit( value, ","), as.numeric ) ]
#update join to get the coordinates to calculate distance with (join on Cx-value)
dt1[ dt2, `:=`( x_XY = i.x_XY, y_XY = i.y_XY ), on = .(variable) ]
#calculate eucledian distances
dt1[, distances := sqrt( (x_XY - x_AB )^2 + (y_XY - y_AB)^2 ) ]

вывод

#     variable value x_AB y_AB x_XY y_XY distances
#  1:       C1   3,1    3    1    3    5  4.000000
#  2:       C1   2,1    2    1    3    5  4.123106
#  3:       C1   2,3    2    3    3    5  2.236068
#  4:       C1   2,2    2    2    3    5  3.162278
#  5:       C1   4,2    4    2    3    5  3.162278
#  6:       C1   2,4    2    4    3    5  1.414214
#  7:       C1   4,1    4    1    3    5  4.123106
#  8:       C1   3,3    3    3    3    5  2.000000
#  9:       C1   2,3    2    3    3    5  2.236068
# 10:       C1   3,1    3    1    3    5  4.000000
# 11:       C2   3,2    3    2    1    2  2.000000
# 12:       C2   3,1    3    1    1    2  2.236068
# 13:       C2   1,2    1    2    1    2  0.000000
# 14:       C2   1,2    1    2    1    2  0.000000
# 15:       C2   0,1    0    1    1    2  1.414214
# 16:       C2   1,4    1    4    1    2  2.000000
# 17:       C2   0,1    0    1    1    2  1.414214
# 18:       C2   1,0    1    0    1    2  2.000000
# 19:       C2   4,2    4    2    1    2  3.000000
# 20:       C2   5,1    5    1    1    2  4.123106
# 21:       C3   2,0    2    0    2    1  1.000000
# 22:       C3   3,2    3    2    2    1  1.414214
# 23:       C3   3,3    3    3    2    1  2.236068
# 24:       C3   1,1    1    1    2    1  1.000000
# 25:       C3   0,1    0    1    2    1  2.000000
# 26:       C3   6,3    6    3    2    1  4.472136
# 27:       C3   2,0    2    0    2    1  1.000000
# 28:       C3   4,2    4    2    2    1  2.236068
# 29:       C3   1,2    1    2    2    1  1.414214
# 30:       C3   3,0    3    0    2    1  1.414214
# 31:       C4   3,1    3    1    5    4  3.605551
# 32:       C4   3,1    3    1    5    4  3.605551
# 33:       C4   2,1    2    1    5    4  4.242641
# 34:       C4   3,1    3    1    5    4  3.605551
# 35:       C4   3,4    3    4    5    4  2.000000
# 36:       C4   2,1    2    1    5    4  4.242641
# 37:       C4   4,3    4    3    5    4  1.414214
# 38:       C4   0,2    0    2    5    4  5.385165
# 39:       C4   2,3    2    3    5    4  3.162278
# 40:       C4   2,5    2    5    5    4  3.162278
# 41:       C5   2,2    2    2    4    3  2.236068
# 42:       C5   3,1    3    1    4    3  2.236068
# 43:       C5   2,1    2    1    4    3  2.828427
# 44:       C5   3,1    3    1    4    3  2.236068
# 45:       C5   1,0    1    0    4    3  4.242641
# 46:       C5   2,0    2    0    4    3  3.605551
# 47:       C5   1,1    1    1    4    3  3.605551
# 48:       C5   1,1    1    1    4    3  3.605551
# 49:       C5   4,1    4    1    4    3  2.000000
# 50:       C5   2,1    2    1    4    3  2.828427
#     variable value x_AB y_AB x_XY y_XY distances

обновление

формат вывода изменен на широкий

#create id's to cast on
dt1[, id := rowidv( dt1, cols = "variable" ) ]
#cast to wide
dcast( dt1, id~variable, value.var = "distances" )

#    id       C1       C2       C3       C4       C5
# 1:  1 4.000000 2.000000 1.000000 3.605551 2.236068
# 2:  2 4.123106 2.236068 1.414214 3.605551 2.236068
# 3:  3 2.236068 0.000000 2.236068 4.242641 2.828427
# 4:  4 3.162278 0.000000 1.000000 3.605551 2.236068
# 5:  5 3.162278 1.414214 2.000000 2.000000 4.242641
# 6:  6 1.414214 2.000000 4.472136 4.242641 3.605551
# 7:  7 4.123106 1.414214 1.000000 1.414214 3.605551
# 8:  8 2.000000 2.000000 2.236068 5.385165 3.605551
# 9:  9 2.236068 3.000000 1.414214 3.162278 2.000000
#10: 10 4.000000 4.123106 1.414214 3.162278 2.828427

из одного go (а также с пропущенным первым столбцом)

dcast( dt1, rowidv( dt1, cols = "variable" )~variable, value.var = "distances" )[, -1]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...