在某些行中已存在数据时获取数据框中的每个组合(R)

时间:2014-09-08 21:29:54

标签: r reshape2

我最近刚刚使用dcast(在reshape2包中)将我的数据帧从长格式压缩到宽格式(因为我需要计数)。现在,我需要用0补充不存在的组合。我想我可以在基础包中使用expand.grid做一些事情,但我不确定(?)因为我不是只是想要每一个组合,但我也有一些重要性。我的一个例子:

AgeGroup Sex Month Count 
10       F   2     4
10       F   6     1
11       M   6     2

我想要的是什么:

AgeGroup Sex Month Count
10       F   2     4
10       F   3     0
10       F   4     0 
10       F   5     0
10       F   6     1

编辑以回应Anada的评论:

最低可重复数据/代码:

library(reshape2)

Sex <- c('M', 'F', 'F', 'F', 'M')
County <- c(41, 65, 35, 49, 41)
AgeGroup <- c(11, 10, 18, 11, 11)
Month <- c(1, 1, 2, 4, 1)
Count <- rep(1, 5)
DF <- cbind.data.frame(Sex, County, AgeGroup, Month, Count)

DF <-dcast(DF, County+Sex+Month+AgeGroup~Count, 
           value.var="Count", length)

names(DF)[names(DF)=='1'] <- 'Count'

请注意,在此示例中,两个观察结果的目的是相同的,以演示我想如何折叠事物。我也不知道为什么,但是dcast重命名了Count列,所以我必须在最后更改名称。

3 个答案:

答案 0 :(得分:0)

以下是基础R的解决方案。如果df是您的数据框,您可以尝试:

    res<-expand.grid(lapply(df[,1:3],unique))
    res$Count<-0
    res$Count[match(do.call(paste,df[,1:3]),do.call(paste,res[,1:3]))]<-df$Count

您评估每列的唯一值,并通过expand.grid从它们构建data.frame。接下来,将每个Count设置为零,并更新原始data.frame中与值匹配的那些。

答案 1 :(得分:0)

这是一个(快速)data.table解决方案(假设您的数据名为df

library(data.table)
setkey(setDT(df), AgeGroup, Sex, Month) # Sorting/keying your data set for future merge
combs <- df[, CJ(unique(AgeGroup), unique(Sex), seq_len(max(Month)))] # CJ is data.tables equivalent expand.grid, but more efficient 
final <- df[combs] # Merging
final[is.na(Count), Count := 0] # Setting all missing combinations to zero
final
#     AgeGroup Sex Month Count
#  1:       10   F     1     0
#  2:       10   F     2     4
#  3:       10   F     3     0
#  4:       10   F     4     0
#  5:       10   F     5     0
#  6:       10   F     6     1
#  7:       10   M     1     0
#  8:       10   M     2     0
#  9:       10   M     3     0
# 10:       10   M     4     0
# 11:       10   M     5     0
# 12:       10   M     6     0
# 13:       11   F     1     0
# 14:       11   F     2     0
# 15:       11   F     3     0
# 16:       11   F     4     0
# 17:       11   F     5     0
# 18:       11   F     6     0
# 19:       11   M     1     0
# 20:       11   M     2     0
# 21:       11   M     3     0
# 22:       11   M     4     0
# 23:       11   M     5     0
# 24:       11   M     6     2

答案 2 :(得分:0)

如果我理解你的要求是正确的,我相信你可以用Hadley Wickham的另一个包来做到这一点:plyr

使用ddply函数并指定.drop = F

尝试:

ddply(df, .(AgeGroup, Sex, Month),length, .drop = F)