Сначала мы переносим набор данных с широкого на длинный, а затем выполняем наши вычисления и, наконец, фильтры преобразуем его обратно в широкоформатный.
library(dplyr)
library(tidyr)
gather(df, k,val,-c(Code,Quarter,StartingYear)) %>%
mutate(Quar=gsub('Quarter(\\d)_.*','\\1',k),year=gsub('Quarter\\d_Num\\.(.*)\\.(.*)','\\1-\\2',k)) %>%
arrange(Code) %>% group_by(Code) %>%
mutate(flag=cumsum(cumsum(Quarter==Quar & StartingYear==year)), Quarter1=paste0('Quarter',flag,'_Starting_Num')) %>%
filter(between(flag,1,5)) %>% select(Code,Quarter1,val) %>% spread(Quarter1,val)
# A tibble: 2 x 6
# Groups: Code [2]
Code Quarter1_Starting_Num Quarter2_Starting_Num Quarter3_Starting_Num Quarter4_Starting_Num Quarter5_Starting_Num
<fct> <int> <int> <int> <int> <int>
1 S2249 23 0 0 2 0
2 S463 4 0 0 4 90
Данные
df <- structure(list(Code = structure(1:2, .Label = c("S2249", "S463"
), class = "factor"), Quarter = 2:3, StartingYear = structure(c(1L,
1L), .Label = "FY16-17", class = "factor"), Quarter1_Num.FY16.17 = c(0L,
0L), Quarter2_Num.FY16.17 = c(23L, 0L), Quarter3_Num.FY16.17 = c(0L,
4L), Quarter4_Num.FY16.17 = c(0L, 0L), Quarter1_Num.FY17.18 = c(2L,
0L), Quarter2_Num.FY17.18 = c(0L, 4L), Quarter3_Num.FY17.18 = c(6L,
90L), Quarter4_Num.FY17.18 = c(0L, 8L)), class = "data.frame", row.names = c(NA,
-2L))
PS: я изменил S463 3 FY17-18
на S463 3 FY16-17
, чтобы соответствовать ожидаемому результату, вы можете оставить S463 3 FY17-18
, но вы получите NA для Q3 до Q5
gsub('Quarter(\\d)_.*','\\1',c('Quarter1_Num.FY16.17','Quarter4_Num.FY17.18'))
[1] "1" "4"
'Quarter(\\d)_.*'
сгруппировать одну цифру, т. Е. 1-9 после четверти и до _, и вернуть эту группу, используя
\\1
gsub('Quarter\\d_Num\\.(.*)\\.(.*)','\\1-\\2',c('Quarter1_Num.FY16.17','Quarter4_Num.FY17.18'))
[1] "FY16-17" "FY17-18"
\\.
пропустить буквальную точку после Quarter, за которой следует digit_Num. В регулярном выражении мы пропускаем специальные символы, такие как
.
, используя
\\
(.*)
сгруппировать все, что угодно, после точки и до следующей точки в одну группу, т.е.
gsub
будет рассматривать это как группу 1
\\.
пропустить буквальную точку
(.*)
сгруппируйте что-нибудь после точки в одну группу, то есть 17 и 18,
gsub
будет рассматривать это как группу 2
\\1-\\2
возврат группы 1 и группы 2, разделенных на
-
, т. Е. 16-17 финансовых годов