我以宽格式获得以下数据,其中每一行代表一个展示厅,“季度”是该展示厅从哪个季度开始销售的,“开始年份”是“开始财务年度”。
Code Quarter StartingYear Quarter1_Num.FY16-17 Quarter2_Num.FY16-17 Quarter3_Num.FY16-17 Quarter4_Num.FY16-17 Quarter1_Num.FY17-18 Quarter2_Num.FY17-18 Quarter3_Num.FY17-18 Quarter4_Num.FY17-18
S2249 2 FY16-17 0 23 0 0 2 0 6 0
S463 3 FY17-18 0 0 4 0 0 4 90 8
对于每个代理,我必须从基于季度和起始年份的列开始(第1行为Quarter2_Num.FY16-17),并涵盖一年的时间,在这种情况下,这意味着为Quarter2_Num.FY17-18。 可以看出,列名称基于Quarter和StartingYear。
我想得到的输出:
Code Quarter1_Starting_Num Quarter2_Starting_Num Quarter3_Starting_Num Quarter4_Starting_Num Quarter5_Starting_Num
S2249 23 0 0 2 0
S463 4 0 0 4 90
这些列捕获陈列室启动后每个季度中一年的数据。
我知道使用gsub可以获得包含FY16-17或FY17-18的列。 但是我不确定如何为每行指定起始列,然后再对N行进行遍历。
有人可以帮我吗?
答案 0 :(得分:1)
首先,我们将数据集从宽到长传输,然后进行计算和过滤,最后将其转换回宽格式。
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
,但您会获得从Q3到Q5的NAs。
gsub('Quarter(\\d)_.*','\\1',c('Quarter1_Num.FY16.17','Quarter4_Num.FY17.18'))
[1] "1" "4"
'Quarter(\\d)_.*'
将一位数字分组,即在Quarter之后和_之前的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。在正则表达式中,我们使用.
跳过诸如\\
之类的特殊字符
(.*)
将点之后和下一个点之前的所有内容分组,即2016财年和2017财年。 gsub
会将其视为第1组
\\.
跳过文字点
(.*)
将点后的任何内容归为一组,即17和18,gsub
会将其视为组2
\\1-\\2
返回由-
隔开的第1组和第2组,即2016-17财年