Переупорядочить ГИС-данные Origina Destination по одной строке в каждой точке - PullRequest
1 голос
/ 10 января 2020

Я начинаю с «широкого» набора данных ГИС-данных исходных пунктов назначения (OD), которые я хочу перегруппировать в более длинный набор данных по одной строке для каждой точки. Мне уже удалось растаять, а затем выпустить dcast, чтобы изменить порядок первого слоя OD, но я натыкаюсь на следующий шаг

Мой MWE - пример поездки из Брюсселя в Лондон на трех этапах. Но есть намного больше идентификаторов, и они могут иметь больше или меньше ног.

library(data.table)

Start = c("Brussels","Lille","Dover")
Start_lon <- c(4.3570964,3.075685,1.3047866)
Start_lat <- c(50.845504, 50.6390876,51.12623)
Border = c("Baisieux", "Frethun","London")
Border_lon = c(3.075685,1.811221, -0.1244124)
Border_lat <- c(50.61848,  50.90148, 51.53165)

df <- data.table(ID = 1,
                 Sub_ID = 1:3,
                 Start = Start, 
                 Start_lon = Start_lon,
                 Start_lat,
                 Border = Border,
                 Border_lon = Border_lon,
                 Border_lat = Border_lat)

Таким образом, у меня есть один идентификатор с тремя Sub_ID, каждый с двумя точками, и, наконец, я ожидаю 6 строк для каждого идентификатора для каждой станции. Мне удается расширить данные с 3 до 6 строк, чтобы одна строка была точкой начала / начала, а другая - границей / точкой назначения, указанной в переменной типа.

df_long <- melt(df, id.vars = c("ID", "Sub_ID", "Start", "Border"))
df_long <- df_long[, c("Type", "Coordinates") := tstrsplit(variable, "_", fixed=TRUE)]
df_long <- dcast(df_long, ID+Sub_ID+Start+Border+Type~Coordinates, value.var="value")

Теперь я не знаю, как перейти к структуре ID == 1 и шести Sub_Ids, чтобы я получил 6 рядов со станциями для
Brussels- Baisieux - Lill- Frethun - Dover- London

Я надеялся получить что-то вроде этого

df_goal <- data.table(ID = 1,
                      Sub_ID = 1:6,
                      Stop = c("Brussels","Baisieux","Lille", "Frethun", "Dover", "London"),
                      lat = NA,
                      lon = NA)

Возможно, все еще с информацией, если остановка "Старт" или "Граница"

1 Ответ

1 голос
/ 10 января 2020

Позвольте мне оставить то, что я пробовал с подходом Tidyverse. Я разделил данные на ID. (У вас есть только один идентификатор, но у вас может быть несколько идентификаторов. Поэтому я решил go таким образом.) Для каждого компонента списка я выбрал столбцы в диапазоне от Start до Border_lat, транспонировал, не включил их в список, затем создал матрица. Я заполнил эту матрицу тремя столбцами (city, lon и lat) и преобразовал матрицу во фрейм данных. Для каждой группы идентификаторов я добавил новый столбец с именем Type. Я повторил Start и Border здесь. Наконец, я изменил имена столбцов и преобразовал lon и lat в цифру c. Я уверен, что есть краткие способы справиться с этим.

library(dplyr)
library(purrr)

map_dfr(.x = split(df, f = df$ID),
        .f = function(x){dplyr::select(x, Start:Border_lat) %>% 
                         t %>% 
                         unlist %>% 
                         matrix(ncol = 3, byrow = TRUE) %>% 
                         as.data.frame(stringsAsFactors = FALSE)},
        .id = "ID") %>% 
group_by(ID) %>% 
mutate(Type = rep(c("Start", "Border"), times = n()/2)) %>% 
rename(stop = "V1", lon = "V2", lat = "V3") %>% 
mutate_at(vars(lon:lat),
          .funs = list(~as.numeric(.)))

#   ID    stop        lon   lat Type  
#   <chr> <chr>     <dbl> <dbl> <chr> 
# 1 1     Brussels  4.36   50.8 Start 
# 2 1     Baisieux  3.08   50.6 Border
# 3 1     Lille     3.08   50.6 Start 
# 4 1     Frethun   1.81   50.9 Border
# 5 1     Dover     1.30   51.1 Start 
# 6 1     London   -0.124  51.5 Border
# 7 2     Brussels  4.36   50.8 Start 
# 8 2     Baisieux  3.08   50.6 Border
# 9 2     Lille     3.08   50.6 Start 
#10 2     Frethun   1.81   50.9 Border
#11 2     Dover     1.30   51.1 Start 
#12 2     London   -0.124  51.5 Border

Другой вариант

Это идея с data.table. Исходя из того, что вы сказали, количество столбцов равно 8, а количество строк варьируется для каждого идентификатора. Учитывая это, я придумал следующий путь.

df[, .(Stop = c(Start, Border),
       Type = c("Start", "Border"),
       lon = c(Start_lon, Border_lon),
       lat = c(Start_lat, Border_lat)),
   by = .(ID, Sub_ID)]

#    ID Sub_ID     Stop   Type        lon      lat
# 1:  1      1 Brussels  Start  4.3570964 50.84550
# 2:  1      1 Baisieux Border  3.0756850 50.61848
# 3:  1      2    Lille  Start  3.0756850 50.63909
# 4:  1      2  Frethun Border  1.8112210 50.90148
# 5:  1      3    Dover  Start  1.3047866 51.12623
# 6:  1      3   London Border -0.1244124 51.53165
# 7:  2      1 Brussels  Start  4.3570964 50.84550
# 8:  2      1 Baisieux Border  3.0756850 50.61848
# 9:  2      2    Lille  Start  3.0756850 50.63909
#10:  2      2  Frethun Border  1.8112210 50.90148
#11:  2      3    Dover  Start  1.3047866 51.12623
#12:  2      3   London Border -0.1244124 51.53165

ДАННЫЕ

df <- structure(list(ID = c(1, 1, 1, 2, 2, 2), Sub_ID = c(1L, 2L, 3L, 
1L, 2L, 3L), Start = c("Brussels", "Lille", "Dover", "Brussels", 
"Lille", "Dover"), Start_lon = c(4.3570964, 3.075685, 1.3047866, 
4.3570964, 3.075685, 1.3047866), Start_lat = c(50.845504, 50.6390876, 
51.12623, 50.845504, 50.6390876, 51.12623), Border = c("Baisieux", 
"Frethun", "London", "Baisieux", "Frethun", "London"), Border_lon = c(3.075685, 
1.811221, -0.1244124, 3.075685, 1.811221, -0.1244124), Border_lat = c(50.61848, 
50.90148, 51.53165, 50.61848, 50.90148, 51.53165)), row.names = c(NA, 
-6L), class = c("data.table", "data.frame"))
...