在数据框中插入缺失时间观察
Inserting missing time observations in a dataframe
我有一个数据框:
zz <- "Product Quarter Million
AAA 2013-Q3 81.1
AAA 2013-Q4 50.5
AAA 2014-Q1 81.9
AAA 2014-Q4 78.3
BBB 2013-Q3 29.9
BBB 2013-Q4 17
BBB 2014-Q3 87.4
BBB 2014-Q4 63
CCC 2013-Q4 41.1
CCC 2014-Q1 59.1
CCC 2014-Q2 110.7
CCC 2014-Q3 127"
df <- read.table(text = zz, header = TRUE); rm(zz)
观察跨度:
2013-Q3
2013-Q4
2014-Q1
2014-Q2
2014-Q3
2014-Q4
除此之外,大多数 Products
都缺少时间观测值。
我需要将缺失的句点作为零插入:
Product Quarter Million
AAA 2013-Q3 81.1
AAA 2013-Q4 50.5
AAA 2014-Q1 81.9
AAA 2014-Q2 0
AAA 2014-Q3 0
AAA 2014-Q4 78.3
BBB 2013-Q3 29.9
BBB 2013-Q4 0
BBB 2014-Q1 0
BBB 2014-Q2 0
BBB 2014-Q3 87.4
BBB 2014-Q4 63
CCC 2013-Q3 0
CCC 2013-Q4 41.1
CCC 2014-Q1 59.1
CCC 2014-Q2 110.7
CCC 2014-Q3 127
CCC 2014-Q4 0
您可以使用 reshape2
包来完成:
library(reshape2)
df <- melt(dcast(df, Product ~ Quarter))
然后您可以将 NA 值更改为 0:
df[is.na(df)] <- 0
你可以试试:
library(data.table)
setkey(setDT(df), Product, Quarter)[CJ(unique(Product), unique(Quarter))][!df, Million:=0][]
# 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
下面的两种解决方案都假设每个季度至少出现在一种产品中,就像问题中的情况一样:
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
转换为动物园对象 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
试试这个
Values = as.data.frame(table(df$Product,df$Quarter))
Values = Values[with(Values, order(Var1, Var2)), ]
colnames(Values)[1] = 'Product'
colnames(Values)[2] = 'Quarter'
data = merge(x = Values, y = df, by =c("Product","Quarter"), all.x=TRUE)
data[is.na(data)] <- 0
data = data[,c(1,2,4)]
对于 R
人来说,也许解决方案有点过于冗长,但它使用 dplyr
# all products from your dataframe
product <- unique(df$Product) # all products from your dataframe
# all quarters you want
quarter <- c('2013-Q3', '2013-Q4', '2014-Q1', '2014-Q2', '2014-Q3', '2014-Q4')
# let's combine them
df2 <- expand.grid(Product=product, Quarter = quarter)
# and now let's do a join between your df and all possible
# combinations of Products and Quarters
df %>%
right_join(df2) %>% # here the join
arrange(Product, Quarter) %>% # here the sorting
mutate(Value = ifelse(is.na(Million),0, Million)) # replacing the NA with 0
我有一个数据框:
zz <- "Product Quarter Million
AAA 2013-Q3 81.1
AAA 2013-Q4 50.5
AAA 2014-Q1 81.9
AAA 2014-Q4 78.3
BBB 2013-Q3 29.9
BBB 2013-Q4 17
BBB 2014-Q3 87.4
BBB 2014-Q4 63
CCC 2013-Q4 41.1
CCC 2014-Q1 59.1
CCC 2014-Q2 110.7
CCC 2014-Q3 127"
df <- read.table(text = zz, header = TRUE); rm(zz)
观察跨度:
2013-Q3 2013-Q4 2014-Q1 2014-Q2 2014-Q3 2014-Q4
除此之外,大多数 Products
都缺少时间观测值。
我需要将缺失的句点作为零插入:
Product Quarter Million
AAA 2013-Q3 81.1
AAA 2013-Q4 50.5
AAA 2014-Q1 81.9
AAA 2014-Q2 0
AAA 2014-Q3 0
AAA 2014-Q4 78.3
BBB 2013-Q3 29.9
BBB 2013-Q4 0
BBB 2014-Q1 0
BBB 2014-Q2 0
BBB 2014-Q3 87.4
BBB 2014-Q4 63
CCC 2013-Q3 0
CCC 2013-Q4 41.1
CCC 2014-Q1 59.1
CCC 2014-Q2 110.7
CCC 2014-Q3 127
CCC 2014-Q4 0
您可以使用 reshape2
包来完成:
library(reshape2)
df <- melt(dcast(df, Product ~ Quarter))
然后您可以将 NA 值更改为 0:
df[is.na(df)] <- 0
你可以试试:
library(data.table)
setkey(setDT(df), Product, Quarter)[CJ(unique(Product), unique(Quarter))][!df, Million:=0][]
# 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
下面的两种解决方案都假设每个季度至少出现在一种产品中,就像问题中的情况一样:
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
转换为动物园对象 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
试试这个
Values = as.data.frame(table(df$Product,df$Quarter))
Values = Values[with(Values, order(Var1, Var2)), ]
colnames(Values)[1] = 'Product'
colnames(Values)[2] = 'Quarter'
data = merge(x = Values, y = df, by =c("Product","Quarter"), all.x=TRUE)
data[is.na(data)] <- 0
data = data[,c(1,2,4)]
对于 R
人来说,也许解决方案有点过于冗长,但它使用 dplyr
# all products from your dataframe
product <- unique(df$Product) # all products from your dataframe
# all quarters you want
quarter <- c('2013-Q3', '2013-Q4', '2014-Q1', '2014-Q2', '2014-Q3', '2014-Q4')
# let's combine them
df2 <- expand.grid(Product=product, Quarter = quarter)
# and now let's do a join between your df and all possible
# combinations of Products and Quarters
df %>%
right_join(df2) %>% # here the join
arrange(Product, Quarter) %>% # here the sorting
mutate(Value = ifelse(is.na(Million),0, Million)) # replacing the NA with 0