Нумерация поколений назад во времени (gen: 0, -1, -2 и т. Д.) Внутри групп в кадре данных - PullRequest
2 голосов
/ 09 мая 2019

Я работаю с фреймом данных, который включает в себя разные группы и у всех есть диапазон лет. Примерно так:

df <- data.frame(group = c(rep("aaa", 3), rep("bbb", 3), rep("ccc", 3)), year = c(2016:2018))
df  

   group  year  
1  aaa    2016  
2  aaa    2017
3  aaa    2018
4  bbb    2016
5  bbb    2017
6  bbb    2018
7  ccc    2016
8  ccc    2017
9  ccc    2018  

То, что я хотел бы сделать, - это создать столбец (поколение), которому присваивается значение на основе года, и в котором последним поколением является поколение 0 и которое учитывает обратное значение для старших поколений. Как это:

   group  year  generation
1  aaa    2018  0
2  bbb    2018  0
3  ccc    2018  0
4  aaa    2017  -1
5  bbb    2017  -1
6  ccc    2017  -1 
7  aaa    2016  -2
8  bbb    2016  -2
9  ccc    2016  -2

Я считаю, что это должно быть что-то вроде следующего, однако это дает мне диапазон от 1 до 3 вместо -2 до 0:

df2 <- df %>% 
  group_by(group) %>% 
  arrange(desc(year)) %>% 
  mutate(generation = min_rank(year))
df2

   group  year  generation
1  aaa    2018  3
2  bbb    2018  3
3  ccc    2018  3
4  aaa    2017  2
5  bbb    2017  2
6  ccc    2017  2 
7  aaa    2016  1
8  bbb    2016  1
9  ccc    2016  1

Есть идеи, как получить желаемый диапазон? Спасибо!

Ответы [ 3 ]

6 голосов
/ 09 мая 2019

Если year не всегда является последовательным, мы можем order year и вычесть его из общего числа строк в группе.

library(dplyr)
df %>%
  group_by(group) %>%
  mutate(generation = -(n() - order(year))) %>%
  arrange(desc(year))

# group  year generation
#  <fct> <int>      <int>
#1 aaa    2018          0
#2 bbb    2018          0
#3 ccc    2018          0
#4 aaa    2017         -1
#5 bbb    2017         -1
#6 ccc    2017         -1
#7 aaa    2016         -2
#8 bbb    2016         -2
#9 ccc    2016         -2

который с использованием базы R будет

with(df, ave(year, group, FUN = function(x) -(length(x) - order(x))))

Если year является последовательным всегда, мы можем вычесть year из max года в группе.

df %>%
  group_by(group) %>%
  mutate(generation = year - max(year))

и

with(df, year - ave(year, group, FUN = max))
0 голосов
/ 09 мая 2019

Опция с data.table

library(data.table)
setDT(df)[, generation := year - max(year), group][order(- year)]
#    group year generation
#1:   aaa 2018          0
#2:   bbb 2018          0
#3:   ccc 2018          0
#4:   aaa 2017         -1
#5:   bbb 2017         -1
#6:   ccc 2017         -1
#7:   aaa 2016         -2
#8:   bbb 2016         -2
39:   ccc 2016         -2
0 голосов
/ 09 мая 2019

Использование transform.

transform(df[order(-df$year), ], 
          generation=factor(year, labels=-(2:0)))
#   group year generation
# 3   aaa 2018          0
# 6   bbb 2018          0
# 9   ccc 2018          0
# 2   aaa 2017         -1
# 5   bbb 2017         -1
# 8   ccc 2017         -1
# 1   aaa 2016         -2
# 4   bbb 2016         -2
# 7   ccc 2016         -2

Если данные несколько отличаются, например, группа bbb сбой в год 2017

df2 <- df[-5, ]

мы могли бы вставить ave в него, чтобы получить правильное количество поколений.

transform(df2[order(-df2$year), ],
          generation=factor(
            with(df2, ave(as.numeric(group), year, FUN=seq)), 
            labels=-(0:2)))
#   group year generation
# 3   aaa 2018          0
# 6   bbb 2018          0
# 9   ccc 2018          0
# 2   aaa 2017         -1
# 8   ccc 2017         -1
# 1   aaa 2016         -2
# 4   bbb 2016         -1
# 7   ccc 2016         -2

Данные

df <- structure(list(group = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 3L, 
3L, 3L), .Label = c("aaa", "bbb", "ccc"), class = "factor"), 
    year = c(2016L, 2017L, 2018L, 2016L, 2017L, 2018L, 2016L, 
    2017L, 2018L)), class = "data.frame", row.names = c(NA, -9L
))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...