【问题标题】:Calculate distance between vector of coordinates in 1 df and single coordinates in other df计算 1 df 中的坐标向量与其他 df 中的单个坐标之间的距离
【发布时间】:2020-02-06 13:31:34
【问题描述】:

假设我有以下两个数据框(行不均匀)

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 个观察值)。

我想要一个新的数据框,其中包含 dfXY 变量 1 的观察值与 dfAB 变量 1 中的每个单独观察值之间的距离、dfXY 变量 2 的观察值 1 和变量 2 中每个单独观察值之间的距离dfAB等

如果我们有

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 等...
以及之间的距离:a) 1,2 & 3,2 b) 1,2 & 3,1 c) 1,2 & 1,2 等。
依此类推,所需的输出格式为:

     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()) 的函数,但我不知道如何合并 ~ sqrt((.x$x - .y$x)^2 + (.x$y - .y$y)^2)

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

请注意,我的实际数据集是数千行和列,因此我手动调用行/列是不可行的。

非常感谢任何帮助

【问题讨论】:

    标签: r dataframe coordinates


    【解决方案1】:

    使用提供的示例数据,我来到了这个data.table-approach

    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
    

    一次性(并且还删除了第一列)

    dcast( dt1, rowidv( dt1, cols = "variable" )~variable, value.var = "distances" )[, -1]
    

    【讨论】:

    • 这获取了值,但它使数据集对我来说非常笨拙 - 有没有办法在不转置表格的情况下做同样的事情?最好是在没有原始值的新表中获取距离
    • 如果您对输出格式有偏好,请将所需的输出添加/编辑到您的问题中,并留言。
    • 我已经编辑了我的原始问题以包含所需的输出格式
    猜你喜欢
    • 2021-09-08
    • 1970-01-01
    • 2020-02-12
    • 2010-09-26
    • 2018-06-12
    • 1970-01-01
    • 2020-06-02
    • 2021-04-05
    • 1970-01-01
    相关资源
    最近更新 更多