以下两种解决方案都假设每个季度至少出现在一个产品中,就像问题中的情况一样:
1) xtabs 此解决方案不需要任何包:
xt <- xtabs(Million ~ Quarter + Product, df)
as.data.frame(xt, responseName = "Million")[c(2, 1, 3)]
Product Quarter Million
1 AAA 2013-Q3 81.1
2 AAA 2013-Q4 50.5
3 AAA 2014-Q1 81.9
4 AAA 2014-Q2 0.0
5 AAA 2014-Q3 0.0
6 AAA 2014-Q4 78.3
7 BBB 2013-Q3 29.9
8 BBB 2013-Q4 17.0
9 BBB 2014-Q1 0.0
10 BBB 2014-Q2 0.0
11 BBB 2014-Q3 87.4
12 BBB 2014-Q4 63.0
13 CCC 2013-Q3 0.0
14 CCC 2013-Q4 41.1
15 CCC 2014-Q1 59.1
16 CCC 2014-Q2 110.7
17 CCC 2014-Q3 127.0
18 CCC 2014-Q4 0.0
如果列顺序和列名不必与问题中的完全相同,则可以将其缩短为:
as.data.frame(xtabs(Million ~ Quarter + Product, df))
如果宽格式可以,那么它可以进一步缩短为:
xtabs(Million ~ Quarter + Product, df)
给予:
Product
Quarter AAA BBB CCC
2013-Q3 81.1 29.9 0.0
2013-Q4 50.5 17.0 41.1
2014-Q1 81.9 0.0 59.1
2014-Q2 0.0 0.0 110.7
2014-Q3 0.0 87.4 127.0
2014-Q4 78.3 63.0 0.0
2) zoo 将 df 转换为 zoo 对象 z,然后将每个 NA 替换为零并使用 fortify.zoo 与 melt=TRUE 参数将其转换回长表。
library(zoo)
z <- read.zoo(df, index = 2, FUN = identity, split = 1, header = TRUE)
z <- na.fill(z, 0)
df_full <- fortify.zoo(z, melt = TRUE, name = "Product")[, c(2, 1, 3)]
names(df_full) <- names(df)
给予:
> df_full
Product Quarter Million
1 AAA 2013-Q3 81.1
2 AAA 2013-Q4 50.5
3 AAA 2014-Q1 81.9
4 AAA 2014-Q2 NA
5 AAA 2014-Q3 NA
6 AAA 2014-Q4 78.3
7 BBB 2013-Q3 29.9
8 BBB 2013-Q4 17.0
9 BBB 2014-Q1 NA
10 BBB 2014-Q2 NA
11 BBB 2014-Q3 87.4
12 BBB 2014-Q4 63.0
13 CCC 2013-Q3 NA
14 CCC 2013-Q4 41.1
15 CCC 2014-Q1 59.1
16 CCC 2014-Q2 110.7
17 CCC 2014-Q3 127.0
18 CCC 2014-Q4 NA
如果宽格式 "zoo" 对象可以,则省略最后两行,即省略设置 df_full 及其名称的行,只使用 z。
> z
AAA BBB CCC
2013-Q3 81.1 29.9 0.0
2013-Q4 50.5 17.0 41.1
2014-Q1 81.9 0.0 59.1
2014-Q2 0.0 0.0 110.7
2014-Q3 0.0 87.4 127.0
2014-Q4 78.3 63.0 0.0