R 按组计算所有点对的X和Y差,保留初始列

R 按组计算所有点对的X和Y差,保留初始列,r,dataframe,combinations,distance,difference,R,Dataframe,Combinations,Distance,Difference,我有一个data.frame,其中包含坐标和组信息,如下所示: set.seed(1) df = data.frame(x=round(runif(6,1,100)), y=round(runif(6,100,200)), group=c("A", "A", "B", "B", "B", "A")) 我想从2个点的所有组合中创建一个“differences”data.frame,并计算第一列中X坐标的差值,第二列中Y坐标的差值。我提出了这个代码,但在国际海事组织(imo)看来绝对没有效率: c

我有一个data.frame,其中包含坐标和组信息,如下所示:

set.seed(1)
df = data.frame(x=round(runif(6,1,100)), y=round(runif(6,100,200)), group=c("A", "A", "B", "B", "B", "A"))
我想从2个点的所有组合中创建一个“differences”data.frame,并计算第一列中X坐标的差值,第二列中Y坐标的差值。我提出了这个代码,但在国际海事组织(imo)看来绝对没有效率:

comp.diff = function(H, data) {(data[H[1], 1:2]- data[H[2], 1:2])}
comb = df %>% nrow %>% combn(2) %>% {cbind(., .[2:1, ])} # make all combinations in both ways
apply(comb, 2, comp.diff, data = df) %>% do.call('rbind.data.frame', .)
但我不能再做两件事:

  • 我只想计算(或保留)来自同一组的点对的差异
  • 对于输出矩阵中的每一行,我希望保留有关初始x、初始y和相关组id的信息
我如何以有效的方式实现这一点(很明显,组合的数量随着N的增加而快速增长…) 谢谢

预期产出结构(摘录):

你可以试试

library(tidyverse)
# calculate the combinations per group
combs <- df %>% 
  split(.$group) %>% 
  map(~combn(1:nrow(.),2)) 

# the calcualtion
df %>% 
  mutate(index=1:n()) %>% 
  split(.$group) %>% 
  map2(combs, ., ~data.frame(t(apply(.x, 2, function(i) 
    cbind(paste(.y$index[i], collapse = "-"),
          .y$x[i[1]],.y$x[i[2]],.y$y[i[1]],.y$y[i[2]],
          -diff(.y$x[i]), -diff(.y$y[i])))),stringsAsFactors = F)) %>% 
  bind_rows(.id = "group") %>% 
  dplyr::select(1, index_diff=2, 
                x1_old=3, x2_old=4,
                y1_old=5, y2_old=6,
                diff_x=7,diff_y=8)
库(tidyverse)
#计算每组的组合
梳子%
拆分(.$组)%>%
地图(~combn(1:nrow(.)2))
#计算
df%>%
变异(索引=1:n())%>%
拆分(.$组)%>%
map2(combs,,,~data.frame(t)(应用(.x,2,函数(i))
cbind(粘贴(.y$index[i],collapse=“-”,
.y$x[i[1]]、.y$x[i[2]]、.y$y[i[1]]、.y$y[i[2]],
-差异(.y$x[i]),-diff(.y$y[i]),stringsAsFactors=F))%>%
绑定行(.id=“group”)%>%
dplyr::select(1,index_diff=2,
x1_old=3,x2_old=4,
y1_old=5,y2_old=6,
差异x=7,差异y=8)
编辑 在一个管道中,包括到整数的转换

df %>% 
  mutate(index=1:n()) %>% 
  split(.$group) %>% 
  map(~data.frame(t(apply(combn(1:nrow(.),2), 2, function(i) 
    cbind(paste(.$index[i], collapse = "-"),
          .$x[i[1]],.$x[i[2]],.$y[i[1]],.$y[i[2]],
          -diff(.$x[i]), -diff(.$y[i])))),stringsAsFactors = F)) %>% 
  bind_rows(.id = "group") %>% 
  dplyr::select(1, index_diff=2, 
                x1_old=3, x2_old=4,
                y1_old=5, y2_old=6,
                diff_x=7,diff_y=8) %>% 
  mutate_at(vars(x1_old:diff_y), as.numeric) %>% 
  as.tibble()
# A tibble: 6 x 8
  group index_diff x1_old x2_old y1_old y2_old diff_x diff_y
  <chr> <chr>       <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
1 A     1-2            27     38    194    166    -11     28
2 A     1-6            27     90    194    118    -63     76
3 A     2-6            38     90    166    118    -52     48
4 B     3-4            58     91    163    106    -33     57
5 B     3-5            58     21    163    121     37     42
6 B     4-5            91     21    106    121     70    -15
df%>%
变异(索引=1:n())%>%
拆分(.$组)%>%
映射(~data.frame)t(应用)combn(1:nrow(.),2),2,函数(i)
cbind(粘贴(.$index[i],collapse=“-”),
.$x[i[1]]、.$x[i[2]]、.$y[i[1]]、.$y[i[2]],
-差异(.$x[i]),-diff(.$y[i]),stringsAsFactors=F))%>%
绑定行(.id=“group”)%>%
dplyr::select(1,index_diff=2,
x1_old=3,x2_old=4,
y1_old=5,y2_old=6,
差异x=7,差异y=8)%>%
在(变量(x1旧:差异)处进行变异,如.numeric)%>%
as.tibble()
#一个tibble:6x8
组索引_diff x1_old x2_old y1_old y2_old diff x diff y
1 A 1-2 27 38 194 166-11 28
2 A 1-6 27 90 194 118-63 76
3 A 2-6 38 90 166 118-52 48
4 B 3-4 58 91 163 106-33 57
5 B 3-5 58 21 163 121 37 42
6 B 4-5 91 21 106 121 70-15

是否应将
f
设为
comp.diff
?@Jimbou
df
的最后一行也属于A组,如何计算
df$x
in
group==“A”
c(58,27,38)的协调人。那么您如何得到
-63
的结果呢。第二个问题是您希望保留这两个值中的哪一个。第一个还是第二个?@Jimbou可能会再次运行初始df?第二个问题(好的一个:-)我想这并不重要,因为在
comb
定义中,我用样本数据计算了两种方式的差异(xi-xj)和(xj-xi)?不,它在这里运行。检查
str(df)
并将输出与您的示例数据进行比较。好的,它工作得很好确实结果似乎是正确的,而且比我的代码快得多。谢谢,这真的帮了我的忙!这只是另一个细节(但很容易修复),输出列是字符格式的
df %>% 
  mutate(index=1:n()) %>% 
  split(.$group) %>% 
  map(~data.frame(t(apply(combn(1:nrow(.),2), 2, function(i) 
    cbind(paste(.$index[i], collapse = "-"),
          .$x[i[1]],.$x[i[2]],.$y[i[1]],.$y[i[2]],
          -diff(.$x[i]), -diff(.$y[i])))),stringsAsFactors = F)) %>% 
  bind_rows(.id = "group") %>% 
  dplyr::select(1, index_diff=2, 
                x1_old=3, x2_old=4,
                y1_old=5, y2_old=6,
                diff_x=7,diff_y=8) %>% 
  mutate_at(vars(x1_old:diff_y), as.numeric) %>% 
  as.tibble()
# A tibble: 6 x 8
  group index_diff x1_old x2_old y1_old y2_old diff_x diff_y
  <chr> <chr>       <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
1 A     1-2            27     38    194    166    -11     28
2 A     1-6            27     90    194    118    -63     76
3 A     2-6            38     90    166    118    -52     48
4 B     3-4            58     91    163    106    -33     57
5 B     3-5            58     21    163    121     37     42
6 B     4-5            91     21    106    121     70    -15