Стоимость переноса / использования из предыдущей группы

данные:

structure(list(id = c(1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 5), 
               ax = c("a", "a", "b", "b", "b", "b", "b", "b", "c", "c", 
                      "d", "d", "e"), time = c(1, 3, 0, 2, 4, 5, 6, 8, 7, 9, 10, 
                                               11, 12)), .Names = c("id", "ax", "time"), class = c("data.table", 
                                                                                                   "data.frame"), row.names = c(NA, -13L))

выглядит как:

    id ax time
 1:  1  a    1
 2:  1  a    3
 3:  2  b    0
 4:  2  b    2
 5:  2  b    4
 6:  2  b    5
 7:  2  b    6
 8:  2  b    8
 9:  3  c    7
10:  3  c    9
11:  4  d   10
12:  4  d   11
13:  5  e   12

Я хочу, чтобы max предыдущей группы располагался рядом с фактической группой:

желаемый результат:

    id ax time newCol
 1:  1  a    1     NA
 2:  1  a    3     NA
 3:  2  b    0      3
 4:  2  b    2      3
 5:  2  b    4      3
 6:  2  b    5      3
 7:  2  b    6      3
 8:  2  b    8      3
 9:  3  c    7      8
10:  3  c    9      8
11:  4  d   10      9
12:  4  d   11      9
13:  5  e   12     11

Возможно ли также иметь значение группы «предыдущая-предыдущая»?

Заинтересован в решениях baseR, data.table и tidyverse

Примечание:

Может быть сгруппирован ЛИБО по id или ax. Пример здесь немного повторяется.

Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
8
0
231
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Вот подход dplyr. Ключевым моментом здесь является группировка и разгруппировка при необходимости:

df %>% 
  group_by(ax) %>% 
  mutate(new = time[n()]) %>%
  ungroup() %>%
  mutate(new = lag(new)) %>%
  group_by(ax) %>%
  mutate(new = new[1])

# A tibble: 13 x 4
# Groups:   ax [5]
      id ax     time   new
   <dbl> <chr> <dbl> <dbl>
 1    1. a        1.   NA 
 2    1. a        3.   NA 
 3    2. b        0.    3.
 4    2. b        2.    3.
 5    2. b        4.    3.
 6    2. b        5.    3.
 7    2. b        6.    3.
 8    2. b        8.    3.
 9    3. c        7.    8.
10    3. c        9.    8.
11    4. d       10.    9.
12    4. d       11.    9.
13    5. e       12.   11.

Предполагая, что id совпадает с group:

dfr <- dfr %>% group_by(id) %>% mutate(groupmax = max(time))
dfr$old_group_max <- dfr$groupmax[match(dfr$id - 1, dfr$id)]

Предпоследняя группа оставлена ​​в качестве упражнения :-)

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

Решение data.table:

dtt.max <- dtt[, .(max = max(time)), by = ax]
dtt.max[, max.prev := shift(max)]

dtt[dtt.max, newCol := i.max.prev, on = 'ax']
# > dtt
#     id ax time newCol
#  1:  1  a    1     NA
#  2:  1  a    3     NA
#  3:  2  b    0      3
#  4:  2  b    2      3
#  5:  2  b    4      3
#  6:  2  b    5      3
#  7:  2  b    6      3
#  8:  2  b    8      3
#  9:  3  c    7      8
# 10:  3  c    9      8
# 11:  4  d   10      9
# 12:  4  d   11      9
# 13:  5  e   12     11

Решение data.table с использованием id + 1

library(data.table)
merge(d, setDT(d)[, max(time), id + 1], all.x = TRUE)

придумали что-то подобное, затем сдвиньте / прокрутите переменную id.

Andre Elrico 10.04.2018 15:40

@AndreElrico Если id числовой, то простое решение - простое добавление целого числа.

pogibas 10.04.2018 15:41

конечно в таком случае. Но, конечно, возможно, что идентификатор отсутствует и т.д ... в любом случае хороший материал !!!

Andre Elrico 10.04.2018 15:42

почему-то я получаю следующую ошибку: Error in gmax(time) : grpn [13] != length(x) [11] in gmax

Andre Elrico 10.04.2018 15:47

@AndreElrico Я использую data.table 1.10.4.3

pogibas 10.04.2018 15:48

Чтобы добавить его по ссылке вместо создания новой таблицы: DT[DT[, max(time), by=id+1], on=.(id), v := i.V1] или DT[DT[, max(time), by=id][, id := shift(id, type = "lead")], on=.(id), v := i.V1]

Frank 10.04.2018 17:17

1) Не использует пакеты. Он вычисляет максимум для каждой группы, дающей Ag, а затем отстает, давая LagMax. Наконец, он оставил соединения с использованием merge, которые вернулись в исходный фрейм данных DF:

Ag <- aggregate(time ~ id, DF, max)
LagMax <- transform(Ag, lagmax = c(NA, head(time, -1)), time = NULL)
merge(DF, LagMax, by = "id", all.x = TRUE)

давая:

   id ax time lagmax
1   1  a    1     NA
2   1  a    3     NA
3   2  b    0      3
4   2  b    2      3
5   2  b    4      3
6   2  b    5      3
7   2  b    6      3
8   2  b    8      3
9   3  c    7      8
10  3  c    9      8
11  4  d   10      9
12  4  d   11      9
13  5  e   12     11

2) Сортировка времени внутри id, чтобы мы знали, что максимальное значение - это последнее значение в каждой группе id.

o <- order(factor(DF$id, levels = unique(DF$id)), DF$time)
Time <- DF$time[o]
lagmax <- function(r) if (r[1] == 1) NA else Time[r[1] - 1]
transform(DF, lagmax = ave(seq_along(id), id, FUN = lagmax))

В вопросе значения time уже отсортированы в id, и если это известно, то приведенное выше можно сократить до:

lagmax <- function(r) if (r[1] == 1) NA else DF$time[r[1] - 1]
transform(DF, lagmax = ave(seq_along(id), id, FUN = lagmax))

3) Этот однострочный перевод таблицы данных (2):

library(data.table)
DT <- copy(DF) # don't overwrite DF

setDT(DT)[, g:=rleid(id)][, lagmax := DT$time[.I[1]-1], keyby = c("g", "id")]

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

setDT(DT)[, lagmax := DT$time[.I[1]-1], by = id]

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