In 0:(b - 1) : numerical expression has 6 elements: only the first used

Viewed 65

I've been working on a project which includes times series. My issue is that I don't have information for each year but for the period. I basically want to duplicate each row as long as the period last: for a n year period, I want to create (n-1) new rows with exactly the same informations. So far, so good.

stack = data.frame(c("ville","commune","université","pole emploi", "ministère","collège"),
               c(2014,2015,2016,2014,2015,2014), 
               c(5,3,2,6,4,1))
colnames(stack) = c("benefit recipient","beginning year", "length of the period")

->

b = stack$`beginning year`
stack2 = stack[rep(rownames(stack),b),]

Now what I want to do is to modify the beginning year into the current year. So I want to add one year after one year into each row. To visualise it, here some code where I do it manually (also a screenshot of what I have and what I want on my real project.

stack3 = data.frame(c("ville","ville","ville","ville","ville","commune","commune","commune","université","université","pole emploi","pole emploi","pole emploi","pole emploi","pole emploi","pole emploi", "ministère","ministère","ministère","ministère","collège"),
               c(2014,2015,2016,2017,2018,2015,2016,2017,2016,2017,2014,2015,2016,2017,2018,2019,2015,2016,2017,2018,2014), 
               c(5,5,5,5,5,3,3,3,2,2,6,6,6,6,6,6,4,4,4,4,1))
colnames(stack3) = c("benefit recipient","effective year", "length of the period")

So far, my idea was to split my period and to add the value of this new vector to my table. I tried with the function:

c = c(0:(b-1)) 

But it didn't work, I have the message In 0:(b - 1) : numerical expression has 6 elements: only the first used. It's a shame because it did exactly what I wanted but, only for the first element...

Do you have any idea of how I can solve it ?

Thanks a lot for your time! What I have What I would like to have

3 Answers

Solution using lapply() and seq():

b = stack$`beginning year`
c = stack$`length of the period`
stack2 = stack[rep(rownames(stack),b),]
stack2$`beginning year` = unlist(lapply(1:length(b), function(x) seq(b[x], b[x]+c[x]-1, by=1)))

You can use map2 to create sequence and unnest to create new rows.

library(tidyverse)

stack %>%
  mutate(year = map2(`beginning year`, `beginning year` + `length of the period` - 1, seq)) %>%
  unnest(year)

#  `benefit recipient` `beginning year` `length of the period`  year
#   <chr>                          <dbl>                  <dbl> <int>
# 1 ville                           2014                      5  2014
# 2 ville                           2014                      5  2015
# 3 ville                           2014                      5  2016
# 4 ville                           2014                      5  2017
# 5 ville                           2014                      5  2018
# 6 commune                         2015                      3  2015
# 7 commune                         2015                      3  2016
# 8 commune                         2015                      3  2017
# 9 université                      2016                      2  2016
#10 université                      2016                      2  2017
# … with 11 more rows

We can use rowwise

library(dplyr)
library(tidyr)
stack %>%
   rowwise %>%
   mutate(year = list(`beginning year`:(`beginning year` + 
                     `length of the period` - 1))) %>%
   unnest(year)
Related