Найти максимальное значение, которое соответствует критерию из другого столбца

Я просматриваю некоторые данные расписания общественного транспорта и пытаюсь найти время, когда каждое транспортное средство было на предыдущей остановке. В данных нет 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}))

Какие-нибудь мысли? Большое спасибо!

Каков ваш ожидаемый результат?

Martin Gal 19.11.2022 13:26
Шаблоны Angular PrimeNg
Шаблоны Angular PrimeNg
Как привнести проверку типов в наши шаблоны Angular, использующие компоненты библиотеки PrimeNg, и настроить их отображение с помощью встроенной...
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Если вы веб-разработчик (или хотите им стать), то вы наверняка гик и вам нравятся "Звездные войны". А как бы вы хотели, чтобы фоном для вашего...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Начала с розового дизайна
Начала с розового дизайна
Pink Design - это система дизайна Appwrite с открытым исходным кодом для создания последовательных и многократно используемых пользовательских...
Шлюз в PHP
Шлюз в PHP
API-шлюз (AG) - это сервер, который действует как единая точка входа для набора микросервисов.
14 Задание: Типы данных и структуры данных Python для DevOps
14 Задание: Типы данных и структуры данных Python для DevOps
проверить тип данных используемой переменной, мы можем просто написать: your_variable=100
1
1
53
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете объединить данные сами по себе, сопоставив 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 19.11.2022 18:37

Нет причин @r2evans.. Я делаю это редко; когда я это делаю, обычно это происходит с соединениями.. т.е. Мне нравится inner_join(x,y), а не x %>% inner_join(y), но вы хорошо заметили, что вложенный канал может сбивать с толку/трудно читать

langtang 19.11.2022 18:41

Спасибо. Не критика. Я понимаю, что смотрю на это через призму «до-dplyr», и видеть такие вещи, как mu <- vec %>% mean(.), кажется ненужным (и, на мой взгляд, не приближается к упрощению сложного выражения, где %>%-каналы часто очень полезны ). Это также может быть связано с тем, что я изучил шепелявость и схему задолго до R, поэтому, хотя мне нравится %>% в более длинных пайпах, меня не беспокоит боль в скобках, которую R может вызвать, если автор выберет. (Это, а также использование IDE, которая упрощает навигацию по скобкам.)

r2evans 19.11.2022 18:48

Другие вопросы по теме