【问题标题】:Comparing xy coordinates in a dataframe比较数据框中的 xy 坐标
【发布时间】:2018-08-02 21:35:28
【问题描述】:

我目前有一个这样的数据框:

x        y       category
159.5    143.5   1
157.5    180.5   1
127.5    159.5   1
115.5    115.5   2
179.5    101.5   2
97.5     103.5   2
149.5    397.5   3
179.5    297.5   3

我想将每个点与数据框中的每个其他点进行比较。我想得到 x 和 y 的差异(即点 159.5、143.5 到点 157.5、180.5 将是 x 中的 2 和 y 中的 +37 的绝对差异)

我尝试过多种方式来做到这一点,但我没有接近,并且使用了太多太慢的 for 循环。我很肯定有一种 dplyr/function 方法可以做到这一点,这真的很有帮助。

这是我的示例输出目标(未全部填写,但总体思路):

x        y        abs x-diff   y-diff  category            
159.5    143.5    0            0       1         (from 159.5    143.5)    
159.5    143.5    2            37      1         (from 157.5    180.5)
159.5    143.5    32           16      1         (from 127.5    159.5)
157.5    180.5    0            0       1         (from 157.5    180.5)
157.5    180.5    2            -37     1         (from 159.5    143.5)
157.5    180.5                         1
127.5    159.5    0            0       1
127.5    159.5                         1
127.5    159.5                         1
115.5    115.5    0           0        2         (from 115.5    115.5)
115.5    115.5    64          -14      2         (from 179.5    101.5)
115.5    115.5    18          -12      2         (from 97.5     103.5)
179.5    101.5    0           0        2
179.5    101.5                         2
179.5    101.5                         2
97.5     103.5    0           0        2
97.5     103.5                         2
97.5     103.5                         2
149.5    397.5    0           0        3
149.5    397.5                         3         
179.5    297.5    0           0        3
179.5    297.5                         3

应该有 3*3(用于第 1 类)、3*3(用于第 2 类)和 2*2(用于第 3 类),总共 22 行。

已编辑:我添加了一个类别变量。我试图修改以前的答案以使其正常工作,但我想比较每个类别中的坐标。其他答案不适用于这个添加的层,因为它会重复整个数据帧 n 次,但对于 group_by 来说更复杂。

【问题讨论】:

    标签: r dataframe dplyr


    【解决方案1】:

    顺便说一句,在您的示例输出中,您在需要正值或负值方面并不一致。例如,159.5 from 157.5 = 2,而159.5 from 190.5157.5 from 159.5 也是正值2,而对于您的y-diff,您有负值和正值。如果您需要绝对值,请考虑在下面的代码中将 xdiffydiff 包装成 abs()

    尽管如此,使用没有循环的基本 R,您可以这样做:

    df <- read.table(text = "
    x        y    
    159.5    143.5
    157.5    180.5
    127.5    159.5
    190.5    198.5
    115.5    115.5
    179.5    101.5
    97.5     103.5
    149.5    397.5", h = T)
    
    df2 <- data.frame(x = rep(df$x, each = dim(df)[1]),
                      y = rep(df$y, each = dim(df)[1]),
                      xdiff = c(sapply(df$x, function(i) i - df$x)),
                      ydiff = c(sapply(df$y, function(j) j - df$y)),
                      fromx = rep(df$x, dim(df)[1]),
                      fromy = rep(df$y, dim(df)[1]))
    
           x     y xdiff ydiff fromx fromy
    1  159.5 143.5     0     0 159.5 143.5
    2  159.5 143.5     2   -37 157.5 180.5
    3  159.5 143.5    32   -16 127.5 159.5
    4  159.5 143.5   -31   -55 190.5 198.5
    5  159.5 143.5    44    28 115.5 115.5
    6  159.5 143.5   -20    42 179.5 101.5
    7  159.5 143.5    62    40  97.5 103.5
    8  159.5 143.5    10  -254 149.5 397.5
    9  157.5 180.5    -2    37 159.5 143.5
    10 157.5 180.5     0     0 157.5 180.5
    11 157.5 180.5    30    21 127.5 159.5
    12 157.5 180.5   -33   -18 190.5 198.5
    13 157.5 180.5    42    65 115.5 115.5
    14 157.5 180.5   -22    79 179.5 101.5
    15 157.5 180.5    60    77  97.5 103.5
    16 157.5 180.5     8  -217 149.5 397.5
    17 127.5 159.5   -32    16 159.5 143.5
    18 127.5 159.5   -30   -21 157.5 180.5
    19 127.5 159.5     0     0 127.5 159.5
    20 127.5 159.5   -63   -39 190.5 198.5
    21 127.5 159.5    12    44 115.5 115.5
    22 127.5 159.5   -52    58 179.5 101.5
    23 127.5 159.5    30    56  97.5 103.5
    24 127.5 159.5   -22  -238 149.5 397.5
    25 190.5 198.5    31    55 159.5 143.5
    26 190.5 198.5    33    18 157.5 180.5
    27 190.5 198.5    63    39 127.5 159.5
    28 190.5 198.5     0     0 190.5 198.5
    29 190.5 198.5    75    83 115.5 115.5
    30 190.5 198.5    11    97 179.5 101.5
    31 190.5 198.5    93    95  97.5 103.5
    32 190.5 198.5    41  -199 149.5 397.5
    33 115.5 115.5   -44   -28 159.5 143.5
    34 115.5 115.5   -42   -65 157.5 180.5
    35 115.5 115.5   -12   -44 127.5 159.5
    36 115.5 115.5   -75   -83 190.5 198.5
    37 115.5 115.5     0     0 115.5 115.5
    38 115.5 115.5   -64    14 179.5 101.5
    39 115.5 115.5    18    12  97.5 103.5
    40 115.5 115.5   -34  -282 149.5 397.5
    41 179.5 101.5    20   -42 159.5 143.5
    42 179.5 101.5    22   -79 157.5 180.5
    43 179.5 101.5    52   -58 127.5 159.5
    44 179.5 101.5   -11   -97 190.5 198.5
    45 179.5 101.5    64   -14 115.5 115.5
    46 179.5 101.5     0     0 179.5 101.5
    47 179.5 101.5    82    -2  97.5 103.5
    48 179.5 101.5    30  -296 149.5 397.5
    49  97.5 103.5   -62   -40 159.5 143.5
    50  97.5 103.5   -60   -77 157.5 180.5
    51  97.5 103.5   -30   -56 127.5 159.5
    52  97.5 103.5   -93   -95 190.5 198.5
    53  97.5 103.5   -18   -12 115.5 115.5
    54  97.5 103.5   -82     2 179.5 101.5
    55  97.5 103.5     0     0  97.5 103.5
    56  97.5 103.5   -52  -294 149.5 397.5
    57 149.5 397.5   -10   254 159.5 143.5
    58 149.5 397.5    -8   217 157.5 180.5
    59 149.5 397.5    22   238 127.5 159.5
    60 149.5 397.5   -41   199 190.5 198.5
    61 149.5 397.5    34   282 115.5 115.5
    62 149.5 397.5   -30   296 179.5 101.5
    63 149.5 397.5    52   294  97.5 103.5
    64 149.5 397.5     0     0 149.5 397.5
    

    如果您愿意,可以考虑通过执行df2[!c(df2$x == df2$fromx &amp; df2$y == df2$fromy),] 删除x == fromxy == fromy 所在的行

    【讨论】:

    • 刚刚编辑了帖子。有没有办法获得使用类别变量的答案?
    【解决方案2】:

    以下是使用outerexpand.grid 构建的所有差异:

    cbind(cbind(with(dat, expand.grid(x=x,x=x)), xdiff=-c( with(dat, outer(x,x,"-") ))),
        cbind( with(dat, expand.grid(y=y,y=y)), ydiff=-c( with(dat, outer(y,y,"-") ))))
    
    #-----------
           x     x xdiff     y     y ydiff
    1  159.5 159.5     0 143.5 143.5     0
    2  157.5 159.5     2 180.5 143.5   -37
    3  127.5 159.5    32 159.5 143.5   -16
    4  190.5 159.5   -31 198.5 143.5   -55
    5  115.5 159.5    44 115.5 143.5    28
    6  179.5 159.5   -20 101.5 143.5    42
    7   97.5 159.5    62 103.5 143.5    40
    8  149.5 159.5    10 397.5 143.5  -254
    9  159.5 157.5    -2 143.5 180.5    37
    10 157.5 157.5     0 180.5 180.5     0
    11 127.5 157.5    30 159.5 180.5    21
    12 190.5 157.5   -33 198.5 180.5   -18
    13 115.5 157.5    42 115.5 180.5    65
    14 179.5 157.5   -22 101.5 180.5    79
      #----snipped rest of 68 rows
    

    【讨论】:

      【解决方案3】:

      在其他地方找到了类似的解决方案。

      diffing_function <- function(i) {
       d <- subset(df, df$category == i)
       R <- expand.grid(i1 = unique(d$id), i2 = unique(d$id))
       R$category <- i
       R$x1 <- d$x[match(R$i1, d$id)]
       R$y1 <- d$y[match(R$i1, d$id)]
       R$x2 <- d$x[match(R$i2, d$id)]
       R$y2 <- d$y[match(R$i2, d$id)]
       R$xdiff <- R$x2 - R$x1
       R$ydiff <- R$y2 - R$y1
       return(R)
      }
      
      results_list <- lapply(unique(df$category), diffing_function)
      results_df <- do.call(rbind, results_list)
      

      【讨论】:

        猜你喜欢
        • 2014-04-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-18
        • 2010-12-06
        • 1970-01-01
        • 2020-08-30
        • 1970-01-01
        相关资源
        最近更新 更多