Фильтрация на основе минимальной разницы дат больше нуля dplyr

У меня есть фрейм данных с двумя столбцами, содержащими даты. Я хотел бы отфильтровать каждую комбинацию идентификатора образца /variable/measurement_date на основе минимальной разницы больше нуля между Measurement_date и date2. Я попытался сгруппировать фрейм данных по идентификатору образца, переменной и Measurement_date, а затем отфильтровать его, заменив все различия дат меньше нуля на NA. Вот мой код:

start_date <- as.Date('2021-01-01')  
end_date <- as.Date('2021-12-30') 
set.seed(1)

cheese <- data.frame(sample_id = c(1,1,1,1,1,1,1,1,1,1,1,1),
                     variable = c('a','a','a','a','a','a',
                                  'b','b','b','b','b','b'),
                     value = runif (n = 12, min = 1, max = 10),
                     measurement_date = c('2021-06-01','2021-06-01','2021-06-01',
                                                  '2021-09-21','2021-09-21','2021-09-21',
                                                  '2021-06-01','2021-06-01','2021-06-01',
                                                  '2021-09-21','2021-09-21','2021-09-21'),
                     date2 = as.Date(sample( as.numeric(start_date): as.numeric(end_date), 12, 
                                             replace = T), 
                                             origin = '1970-01-01'))

library(dplyr)
filtered <- cheese %>% group_by(sample_id, variable, measurement_date)
filtered %>%
  filter(difftime(measurement_date,date2) == 
           min(replace(difftime(measurement_date, date2))>0,NA),na.rm=TRUE)

Это пример кадра данных:

sample_id   variable    value       measurement_date    date2
1           a           3.389578    2021-06-01          2021-03-26
1           a           4.349115    2021-06-01          2021-10-04
1           a           6.155680    2021-06-01          2021-12-28
1           a           9.173870    2021-09-21          2021-11-26
1           a           2.815137    2021-09-21          2021-09-20
1           a           9.085507    2021-09-21          2021-11-25
1           b           9.502077    2021-06-01          2021-03-20
1           b           6.947180    2021-06-01          2021-08-01
1           b           6.662026    2021-06-01          2021-02-06
1           b           1.556076    2021-09-21          2021-04-15
1           b           2.853771    2021-09-21          2021-08-05
1           b           2.589011    2021-09-21          2021-06-14

В этом примере есть четыре комбинации sample_id/переменная/дата измерения:

sample_id, variable, measurement_date
1,a,2021-06-01
1,b,2021-06-01
1,a,2021-09,21
1,b,2021-09-21

Я хотел бы сгруппировать фрейм данных по этим комбинациям, а затем посмотреть на разницу между Measurement_date и date2, найдя минимальную разницу между положительными датами. Таким образом, отфильтрованный фрейм данных должен выглядеть так:

sample_id   variable    value       measurement_date    date2
1           a           3.389578    2021-06-01          2021-03-26
1           b           9.502077    2021-06-01          2021-03-20
1           a           2.815137    2021-09-21          2021-09-20
1           b           2.853771    2021-09-21          2021-08-05

но мой код просто возвращает ошибку..

> Error: Problem with `filter()` input `..1`.
i Input `..1` is `==...`.
x argument "values" is missing, with no default

РЕДАКТИРОВАТЬ

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

cheese$diff <- as.Date(cheese$measurement_date) - cheese$date2
filtered <- cheese %>% group_by(sample_id, variable, measurement_date) %>% 
    filter(diff == min(diff[diff>0]))

Мне непонятно, как ваш ожидаемый результат будет получать значения для «date2» на основе значений в cheese. Вы можете уточнить?

jdobres 23.03.2022 02:03

извините, @jdobres, я понимаю, что мой вопрос был не слишком ясен, и у меня возникла проблема с установкой семени. Я включил исходный фрейм данных в свое редактирование. По сути, я хотел бы сгруппировать фрейм данных по каждой комбинации sample_id, переменной и даты измерения, что в этом примере приведет к трем строкам для каждой группировки, а затем вычислить разницу между Measurement_date и date2, возвращая строку, в которой минимальное положительное значение происходит.

Squan Schmaan 23.03.2022 02:37
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
47
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Мы можем заменить значения, которые меньше или равны 0, на NA, а затем использовать which.min внутри slice, чтобы нам не нужно было создавать новый столбец.

library(tidyverse)

cheese %>%
  mutate(measurement_date = as.Date(measurement_date)) %>%
  group_by(sample_id, variable, measurement_date) %>%
  slice(which.min((measurement_date - date2)*NA^((measurement_date - date2) <=0)))

Выход

  sample_id variable value measurement_date date2     
      <dbl> <chr>    <dbl> <date>           <date>    
1         1 a         3.39 2021-06-01       2021-03-26
2         1 b         9.50 2021-06-01       2021-03-20
3         1 b         2.85 2021-08-22       2021-08-05

Вы также можете напрямую использовать replace вместо более короткой записи.

cheese %>%
  mutate(measurement_date = as.Date(measurement_date)) %>%
  group_by(sample_id, variable, measurement_date) %>%
  slice(which.min(replace((measurement_date - date2), (measurement_date - date2)<=0, NA)))

Данные

cheese <- structure(list(sample_id = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1), variable = c("a", "a", "a", "a", "a", "a", "b", "b", "b", 
"b", "b", "b"), value = c(3.3895779682789, 4.34911509673111, 
6.15568027016707, 9.17387010995299, 2.8151373793371, 9.08550716470927, 
9.50207741744816, 6.94718013238162, 6.66202639508992, 1.55607643420808, 
2.85377117409371, 2.58901077276096), measurement_date = c("2021-06-01", 
"2021-06-01", "2021-06-01", "2021-08-22", "2021-08-22", "2021-08-22", 
"2021-06-01", "2021-06-01", "2021-06-01", "2021-08-22", "2021-08-22", 
"2021-08-22"), date2 = structure(c(18712, 18904, 18989, 18957, 
18890, 18956, 18706, 18840, 18664, 18732, 18844, 18792), class = "Date")), class = "data.frame", row.names = c(NA, 
-12L))

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