R - Создать столбец по количеству элементов группы из другого столбца. - PullRequest
2 голосов
/ 07 апреля 2019

предположим, что у меня есть фрейм данных "raw", который выглядит следующим образом (упрощенно):

raw <- data.frame(year.start = c(2004, 2004, 2004, 2004, 2004, 2010, 2010, 2010),
            year.end = c(2006, 2006, 2006, 2005, 2005, 2012, 2012, 2012),
            id = c("A","A","A","B","B","C","C","C"))

Он состоит из двух столбцов с годами, которые указывают период от начала года до года. Кроме того, каждый период относится к группе продуктов «id». Моя цель - создать новый столбец, в котором период разделен на отдельные годы для каждой группы соответственно. Следовательно, цель должна выглядеть следующим образом:

goal <- data.frame(year.start = c(2004, 2004, 2004, 2004, 2004, 2010, 2010, 2010),
               year.end = c(2006, 2006, 2006, 2005, 2005, 2012, 2012, 2012),
               id = c("A","A","A","B","B","C","C","C"), 
               year.goal = c(2004, 2005, 2006, 2004, 2005, 2010, 2011, 2012))

Есть ли плавный способ сделать это? Я действительно понятия не имею ... Заранее спасибо!

1 Ответ

2 голосов
/ 07 апреля 2019

Решение с использованием dplyr.

library(dplyr)

raw2 <- raw %>%
  group_by(id) %>%
  mutate(year.goal = min(year.start):max(year.end)) %>%
  ungroup()
raw2
# # A tibble: 8 x 4
#   year.start year.end id    year.goal
#        <dbl>    <dbl> <fct>     <int>
# 1       2004     2006 A          2004
# 2       2004     2006 A          2005
# 3       2004     2006 A          2006
# 4       2004     2005 B          2004
# 5       2004     2005 B          2005
# 6       2010     2012 C          2010
# 7       2010     2012 C          2011
# 8       2010     2012 C          2012

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

library(data.table)
setDT(raw)

raw2 <- raw[, year.goal :=  min(year.start):max(year.end), by = id]
raw2[]
#    year.start year.end id year.goal
# 1:       2004     2006  A      2004
# 2:       2004     2006  A      2005
# 3:       2004     2006  A      2006
# 4:       2004     2005  B      2004
# 5:       2004     2005  B      2005
# 6:       2010     2012  C      2010
# 7:       2010     2012  C      2011
# 8:       2010     2012  C      2012

Решение с использованием базы R.

dat_list <- split(raw, f = raw$id)
dat_list2 <- lapply(dat_list, function(x) {
  x$year.goal <- x$year.start[1]:x$year.end[1]
  return(x)
})
raw2 <- do.call(rbind, dat_list2)
raw2
#     year.start year.end id year.goal
# A.1       2004     2006  A      2004
# A.2       2004     2006  A      2005
# A.3       2004     2006  A      2006
# B.4       2004     2005  B      2004
# B.5       2004     2005  B      2005
# C.6       2010     2012  C      2010
# C.7       2010     2012  C      2011
# C.8       2010     2012  C      2012

Решение с использованием tidyverse.

library(tidyverse)

raw2 <- raw %>%
  group_by_all() %>%
  nest() %>%
  mutate(year.goal = map2(year.start, year.end, `:`)) %>%
  unnest()
raw2
# # A tibble: 8 x 4
#   year.start year.end id    year.goal
#        <dbl>    <dbl> <fct>     <int>
# 1       2004     2006 A          2004
# 2       2004     2006 A          2005
# 3       2004     2006 A          2006
# 4       2004     2005 B          2004
# 5       2004     2005 B          2005
# 6       2010     2012 C          2010
# 7       2010     2012 C          2011
# 8       2010     2012 C          2012

Другое решение dplyr.

library(dplyr)
raw2 <- raw %>%
  group_by(id) %>%
  mutate(year.goal = first(year.start) + row_number() - 1) %>%
  ungroup()
raw2
# # A tibble: 8 x 4
#   year.start year.end id    year.goal
#        <dbl>    <dbl> <fct>     <dbl>
# 1       2004     2006 A          2004
# 2       2004     2006 A          2005
# 3       2004     2006 A          2006
# 4       2004     2005 B          2004
# 5       2004     2005 B          2005
# 6       2010     2012 C          2010
# 7       2010     2012 C          2011
# 8       2010     2012 C          2012
...