R - Получение номеров строк пар координат в кадре данных пар координат - PullRequest
0 голосов
/ 27 апреля 2018

Предположим, у меня есть фрейм данных, называемый "ребрами" пар точек, скажем:

  x0       y0       x1       y1
1 2.464286 2.464286 2.583333 1.750000
2 0.700000 3.787500 2.464286 2.464286
3 2.464286 2.464286 3.500000 3.500000
4 3.500000 3.500000 4.300000 3.900000
5 2.250000 4.750000 3.500000 3.500000

Каждая строка кадра данных представляет собой ребро, идущее от точки (x0, y0) к точке (x1, y1), например, мой первый край идет от точки координат (2.464286,2.464286) к точке (2.583333,1.750000)

Из этого фрейма данных я могу легко извлечь другой фрейм данных, назвав его «вершинами», в котором каждая точка появляется только один раз:

  x        y
1 2.464286 2.464286
2 0.700000 3.787500
3 3.500000 3.500000
4 2.250000 4.750000
5 2.583333 1.750000
6 4.300000 3.900000

Как я могу пометить каждую точку в "вершинах" номерами строк, в которых она появляется в "краях" кадра данных, безразлично как левая конечная точка или правая конечная точка? То есть я бы хотел получить что-то вроде этого:

  x        y            occurrences
1 2.464286 2.464286     1,2,3
2 0.700000 3.787500     2
3 3.500000 3.500000     3,4,5
4 2.250000 4.750000     5
5 2.583333 1.750000     1
6 4.300000 3.900000     4

Я пытался использовать% в% и который, но он учитывает только поэлементное сравнение, поэтому две точки с одинаковыми координатами x или y можно считать одинаковыми.

Кроме того, это лабелизация, которую мне придется делать довольно много раз в моих симуляциях, поэтому я надеюсь получить лучшее решение, чем решение for-loop / if based.

Ответы [ 3 ]

0 голосов
/ 27 апреля 2018

Надеюсь, это поможет!

library(dplyr)

edges %>%
  rowwise() %>%
  mutate(occurrences = paste(rownames(vertices)[unlist(lapply(apply(vertices, 1, paste, collapse=","), 
                                  function(i) grepl(paste(x, y, sep=','), i)))], collapse = ",")) %>%
  data.frame()

Вывод:

         x        y occurrences
1 2.464286 2.464286       1,2,3
2 0.700000 3.787500           2
3 3.500000 3.500000       3,4,5
4 2.250000 4.750000           5
5 2.583333 1.750000           1
6 4.300000 3.900000           4

Пример данных:

edges <- structure(list(x = c(2.464286, 0.7, 3.5, 2.25, 2.583333, 4.3), 
    y = c(2.464286, 3.7875, 3.5, 4.75, 1.75, 3.9)), class = "data.frame", row.names = c("1", 
"2", "3", "4", "5", "6"))

vertices <- structure(list(x0 = c(2.464286, 0.7, 2.464286, 3.5, 2.25), y0 = c(2.464286, 
3.7875, 2.464286, 3.5, 4.75), x1 = c(2.583333, 2.464286, 3.5, 
4.3, 3.5), y1 = c(1.75, 2.464286, 3.5, 3.9, 3.5)), class = "data.frame", row.names = c("1", 
"2", "3", "4", "5"))
0 голосов
/ 28 апреля 2018

Это однострочный подход, который не требует dplyr:

vertices[, 'occurrences'] <- apply(vertices, 1, function(V) 
  paste(which(apply(edges, 1, function (E, V) 
    isTRUE(all.equal(V, E[1:2], check.attributes=FALSE)) || 
    isTRUE(all.equal(V, E[3:4], check.attributes=FALSE)), V=V)),
  collapse=',')
)

Код принимает каждую строку vertices по очереди, затем проверяет совпадение в каждой строке edges, проверяя каждый конец строки по очереди. isTRUE необходимо разбить результаты сравнения на простое «соответствует или нет»; which преобразует строку TRUE s и FALSE s в целые числа, соответствующие строкам, а paste преобразует эту серию целых чисел в символьную строку, разделенную запятыми.

Пример данных

vertices<- structure(list(
    x = c(2.464286, 0.7, 3.5, 2.25, 2.583333, 4.3), 
    y = c(2.464286, 3.7875, 3.5, 4.75, 1.75, 3.9)),
    class = "data.frame", 
    row.names = c("1", "2", "3", "4", "5", "6")
)

edges <- structure(list(
   x0 = c(2.464286, 0.7, 2.464286, 3.5, 2.25),
    y0 = c(2.464286, 3.7875, 2.464286, 3.5, 4.75),
    x1 = c(2.583333, 2.464286, 3.5, 4.3, 3.5),
    y1 = c(1.75, 2.464286, 3.5, 3.9, 3.5)),
    class = "data.frame", 
    row.names = c("1", "2", "3", "4", "5")
)

Выход:

> vertices

         x        y occurrences
1 2.464286 2.464286       1,2,3
2 0.700000 3.787500           2
3 3.500000 3.500000       3,4,5
4 2.250000 4.750000           5
5 2.583333 1.750000           1
6 4.300000 3.900000           4
0 голосов
/ 27 апреля 2018

Вот решение, которое использует dplyr. Возможно, есть способ убрать это, но это должно помочь вам в этом.

library(dplyr)

edgedf <- read.table(header = TRUE,stringsAsFactors = FALSE, text = "
x0       y0       x1       y1
2.464286 2.464286 2.583333 1.750000
0.700000 3.787500 2.464286 2.464286
2.464286 2.464286 3.500000 3.500000
3.500000 3.500000 4.300000 3.900000
2.250000 4.750000 3.500000 3.500000")


vertdf <- read.table(header = TRUE,stringsAsFactors = FALSE, text = "
x        y
2.464286 2.464286
0.700000 3.787500
3.500000 3.500000
2.250000 4.750000
2.583333 1.750000
4.300000 3.900000")

# Add row numbers
tmp_edgedf <- edgedf %>% mutate(id = 1:n())
# Stack the x0,y0 and x1,y1 coords as x,y then join
# with vertices "vertdf". Grouping by x,y and summarise
# concatenating the row numbers as occurrences.
rbind(tmp_edgedf %>%
        select(id, x0, y0) %>%
        rename(x = x0, y = y0),
      tmp_edgedf %>%
        select(id, x1, y1) %>%
        rename(x = x1, y = y1)) %>%
  right_join(vertdf, by = c("x", "y")) %>%
  group_by(x, y) %>%
  summarise(occurrences = paste(sort(id), collapse = ",")) %>%
  data.frame() # Remove rounding by tibble object.

Результаты

##          x        y occurrences
## 1 0.700000 3.787500           2
## 2 2.250000 4.750000           5
## 3 2.464286 2.464286       1,2,3
## 4 2.583333 1.750000           1
## 5 3.500000 3.500000       3,4,5
## 6 4.300000 3.900000           4

EDIT

Вот вариант и, возможно, более простое решение ниже. Первый inner_join соединяет вершины с (x0, y0), а второй с (x1, y1). Номер строки добавляется в структуру данных edgedf (временно) для отслеживания номера строки. Фрейм данных edgedf можно просто добавить до объединения, исключая дублирование.

rbind(
    inner_join(vertdf, 
               edgedf %>% transmute(id = 1:n(), x0, y0),
               by = c(x = "x0", y = "y0")),
    inner_join(vertdf,
               edgedf %>% transmute(id = 1:n(), x1, y1),
               by = c(x = "x1", y = "y1"))
  ) %>%
  group_by(x,y) %>%
  summarise(occurrances = paste(sort(id), collapse = ",")) %>%
  data.frame()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...