Вычислить различия X и Y для всех пар точек по группам, сохраняя начальные столбцы - PullRequest
0 голосов
/ 07 июня 2018

У меня есть 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"))

Я хочу создать data.frame "различия" из всех комбинаций из 2 точек и вычислить разницу в 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 иидентификатор соответствующей группы

Как я могу добиться этого эффективным способом (очевидно, число комбинаций быстро растет с N ...) Спасибо

Структура ожидаемой выработки (выписка):

####   delta.x delta.y old.x old.y group
#### 1     -11      28    27   166     A
#### 5     -63      76    27   118     A
#### ...

1 Ответ

0 голосов
/ 07 июня 2018

Вы можете попробовать

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)

Редактировать

и все вместе в одной трубе, включая преобразование в целые числа

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
...