Как создать подмножество из нескольких фреймов данных в списке, содержащем только строки с последовательными номерами в одном из столбцов?

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

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

set.seed(1234)

A <- data.frame("D" = c(sample(1:5, size = 1000, replace = TRUE)), "Temp" = c(sample(0:35, size = 1000, replace = TRUE)))
B <- data.frame("D" = c(sample(1:5, size = 1000, replace = TRUE)), "Temp" = c(sample(-10:22, size = 1000, replace = TRUE)))
C <- data.frame("D" = c(sample(1:5, size = 1000, replace = TRUE)), "Temp" = c(sample(3:42, size = 1000, replace = TRUE)))

climate <- list("Alist" = A, "Blist" = B, "Clist" = C)

# courtesy of ThomasIsCoding
tm <- lapply(
  climate,
  function(x) {
    subset(
      x,
      Temp > quantile(Temp, probs = 0.90)
    )
  }
)
tm

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

result <- lapply(lapply(lapply(
  tm, '[[',1), # this selects the days column in all the dataframes in the list tmax95
  diff), # this finds the difference between each element in the days column to help determine if they are consecutive
  rle) # i don't really understand rle fully but to my understanding this takes all the differences and counts how many there are in order or something like that
result

Затем я использую еще один пример, чтобы найти случаи, когда имеется более двух различий в 1 день (последовательных).

fin <- lapply(result, function(x) x$lengths>=2 & x$values==1)
fin

Однако это не совсем то, что я хочу в качестве конечного результата, поскольку он возвращает список списков значений True и Falses, тогда как мне нужны строки данных, связанные с возвращаемыми значениями True. Как я смогу получить данные за последовательные дни, а не за истинные значения?

Вам придется вернуться к исходным данным, содержащим даты. Предоставленные вами данные не содержат дат.

Edward 09.08.2024 15:36

@Edward В этом случае просто возможности ссылаться на фреймы данных A, B и C со столбцом D должно быть достаточно, чтобы я мог разобраться с исходными данными. Я не использовал исходные данные в качестве образца, поскольку они содержат 20 фреймов данных, каждый из которых содержит около 10 000 строк и 15 столбцов. Было бы более полезно, если бы я поместил сюда исходные данные?

user26711711 09.08.2024 15:46
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
53
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Проверьте, сработает ли это у вас, используя dplyr. Немного неясно, что означает «последовательный» в контексте случайно распределенных дней, но я пока беру данные такими, какие они есть.

library(dplyr)

threshTemp = 20
threshDay = 3

lapply(tm, \(x)
  x %>%
  mutate(cond = Temp > threshTemp, consid = consecutive_id(cond)) %>%
  filter(n() >= threshDay & cond, .by = c(D, consid)) %>%
  select(-cond, -consid))

Случайно распределенные дни предназначены только для создания образца набора данных. В моих исходных данных они основаны на реальных наблюдениях, а затем я выбираю дни, которые превышают определенный температурный порог, в результате чего некоторые дни идут подряд, а большинство нет, если это имеет смысл.

user26711711 09.08.2024 15:53

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

Andre Wildberg 09.08.2024 15:58
Ответ принят как подходящий

Вы можете попробовать следующий код, который сначала применяет порог температуры к каждому климату, используя subset (как вы), а затем подмножества их, используя diff, чтобы найти строки, в которых есть 3 дня подряд.

result <- lapply(climate, \(x) {
  y <- subset(x,
              Temp > quantile(Temp, probs = 0.90)
  )
  
  y[unique(
    sort(
      unlist(
        lapply(
          which(
            c(diff(y[,'D'])==1, FALSE) & c(diff(y[,'D'], diff=2)==0, FALSE, FALSE)), 
          \(x) x + 0:2)
      ))),]
}
)

lapply(result, head)
    $Alist
    D Temp
317 2   35
326 3   33
341 4   34
579 3   34
582 4   33
584 5   35

$Blist
    D Temp
357 2   21
358 3   22
361 4   20

$Clist
    D Temp
257 2   40
258 3   40
269 4   41
350 1   41
351 2   42
364 3   41

Объяснение:

diff() принимает различия каждого элемента. Если установить значение == 1, будут найдены последовательные дни. diff(..., diff=2)==0 находит последовательные равные различия. Вместе эти два условия определяют первый из трех последовательных дней. Добавление FALSE гарантирует, что вектор имеет правильную длину, поскольку дифференцирование каждый раз уменьшает длину на 1.

which находит индексы первых 3 дней подряд. +0:2 дает индексы за 3 дня подряд.

lapply выполняет цикл для каждого дня, и нам нужно unlist это, чтобы получить вектор, отсортировать его, а затем удалить дубликаты с помощью unique.


Данные (climate), указанные в вопросе с set.seed(1234).

Спасибо! Это сработало с небольшими изменениями, но мне было интересно, сможете ли вы объяснить различные функции, которые вы использовали, и что они делают в этом контексте? Даже прочитав документацию R Help, я все еще немного в замешательстве.

user26711711 13.08.2024 13:04

Да - см. мое редактирование для объяснения.

Edward 13.08.2024 13:58

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