Я просматриваю некоторые данные расписания общественного транспорта и пытаюсь найти время, когда каждое транспортное средство было на предыдущей остановке. В данных нет Vehicle_number, поэтому мне просто нужно найти ближайшее время, предшествующее текущему времени в наборе данных для предыдущей остановки.
library(tidyverse)
data <- tribble(~stop,~prev_stop,~time,
5,4,10,
6,5,10.1,
7,6,10.2,
9,7,10.3,
5,4,11,
6,5,11.1,
7,6,11.2,
9,7,11.3,
5,4,12,
6,5,12.1,
7,6,12.2,
9,7,12.3)
Что-то вроде...
data %>%
mutate(time_at_prev_stop = max(time[stop{in another row) == prev_stop{in current row}] & time {in target row}<time{in current row}))
Какие-нибудь мысли? Большое спасибо!
Вы можете объединить данные сами по себе, сопоставив prev_stop с stop, отфильтровать строки так, чтобы time
был в правильном направлении (т. строк данных и выбрав макс.
Вот реализация id
, но я бы рекомендовал dplyr
, потому что она поддерживает неэквивалентные соединения и скользящие соединения.
library(dplyr)
left_join(data %>% mutate(id = row_number()),data,by=c("prev_stop" = "stop")) %>%
filter(time.x>time.y | is.na(time.y)) %>%
arrange(id,desc(time.y)) %>%
group_by(id) %>%
slice_head(n=1) %>%
ungroup() %>%
select(stop, prev_stop, time=time.x, time_at_previous_stop = time.y)
Вывод:
# A tibble: 12 x 4
stop prev_stop time time_at_previous_stop
<dbl> <dbl> <dbl> <dbl>
1 5 4 10 NA
2 6 5 10.1 10
3 7 6 10.2 10.1
4 9 7 10.3 10.2
5 5 4 11 NA
6 6 5 11.1 11
7 7 6 11.2 11.1
8 9 7 11.3 11.2
9 5 4 12 NA
10 6 5 12.1 12
11 7 6 12.2 12.1
12 9 7 12.3 12.2
Реализация data.table с использованием неэквивалентного соединения:
library(data.table)
setDT(data)
data[,`:=`(id=.I,prev_time=time)][data, on=.(stop=prev_stop, prev_time<time)][
,.SD[.N,.(stop=i.stop, time = prev_time, prev_stop=stop, time_at_previous_stop = time)], i.id, keep=F
]
Более читаемая реализация data.table
с использованием скользящего соединения:
d1 = data
d2 = data
setkey(setDT(d1),stop,time)
setkey(setDT(d2),prev_stop, time)
d1[, t:=time][d2,roll=+Inf][,.(stop=i.stop, prev_stop=stop,time, time_at_previous_stop=t)]
Вывод:
stop prev_stop time time_at_previous_stop
1: 5 4 10.0 NA
2: 5 4 11.0 NA
3: 5 4 12.0 NA
4: 6 5 10.1 10.0
5: 6 5 11.1 11.0
6: 6 5 12.1 12.0
7: 7 6 10.2 10.1
8: 7 6 11.2 11.1
9: 7 6 12.2 12.1
10: 9 7 10.3 10.2
11: 9 7 11.3 11.2
12: 9 7 12.3 12.2
Просто любопытно, по какой причине вы выбрали left_join(data %>% mutate(..), data, ..)
вместо data %>% mutate(..) %>% left_join(data, ..)
? Иногда я нахожу, что за вложенными каналами немного сложнее следить.
Нет причин @r2evans.. Я делаю это редко; когда я это делаю, обычно это происходит с соединениями.. т.е. Мне нравится inner_join(x,y)
, а не x %>% inner_join(y)
, но вы хорошо заметили, что вложенный канал может сбивать с толку/трудно читать
Спасибо. Не критика. Я понимаю, что смотрю на это через призму «до-dplyr», и видеть такие вещи, как mu <- vec %>% mean(.)
, кажется ненужным (и, на мой взгляд, не приближается к упрощению сложного выражения, где %>%
-каналы часто очень полезны ). Это также может быть связано с тем, что я изучил шепелявость и схему задолго до R, поэтому, хотя мне нравится %>%
в более длинных пайпах, меня не беспокоит боль в скобках, которую R может вызвать, если автор выберет. (Это, а также использование IDE, которая упрощает навигацию по скобкам.)
Каков ваш ожидаемый результат?