计算所有观察到的因子水平,也计算未观察到的因子水平

问题描述 投票:0回答:3

我们有DF

df <- data.frame(group=as.factor(rep(c("UP","DOWN"),6)),variables=(rep(c("sex","smoke","sport"),each=4))
             ,values=as.factor(c(1,1,1,0  ,1,1,0,0, 1,1,1,1)))

   group variables values
1     UP       sex      1
2   DOWN       sex      1
3     UP       sex      1
4   DOWN       sex      0
5     UP     smoke      1
6   DOWN     smoke      1
7     UP     smoke      0
8   DOWN     smoke      0
9     UP     sport      1
10  DOWN     sport      1
11    UP     sport      1
12  DOWN     sport      1
> 

现在我想知道所有级别的所有计数

library(plyr)

这个命令几乎完全符合我的要求

count(df, c("variables", "group", "values"))

 variables group values freq
1      sex  DOWN     0    1
2      sex  DOWN     1    1
3      sex    UP     1    2
4    smoke  DOWN     0    1
5    smoke  DOWN     1    1
6    smoke    UP     0    1
7    smoke    UP     1    1
8    sport  DOWN     1    2
9    sport    UP     1    2

我还想计算未观察到的因子水平。就像我在下面的输出中一样。

 variables group values freq
1      sex  DOWN     0    1
2      sex  DOWN     1    1
3      sex    UP     0    0  <-- 
4      sex    UP     1    2
5    smoke  DOWN     0    1
6    smoke  DOWN     1    1
7    smoke    UP     0    1  
8    smoke    UP     1    1
9    sport  DOWN     0    0  <--
10   sport  DOWN     1    2
11   sport    UP     0    0  <--
12   sport    UP     1    2

如何实现上述输出?

r count aggregate plyr r-factor
3个回答
2
投票

您也可以使用data.table以更少的代码行完成此操作:

library(data.table)
dt <- setDT(df)
cj <- CJ(dt$variables, dt$group, dt$values, unique = TRUE)
dt[, .N, keyby = c("variables", "group", "values")][cj][is.na(N), N := 0]

print(dt)    
    variables group values N
 1:       sex  DOWN      0 1
 2:       sex  DOWN      1 1
 3:       sex    UP      0 0
 4:       sex    UP      1 2
 5:     smoke  DOWN      0 1
 6:     smoke  DOWN      1 1
 7:     smoke    UP      0 1
 8:     smoke    UP      1 1
 9:     sport  DOWN      0 0
10:     sport  DOWN      1 2
11:     sport    UP      0 0
12:     sport    UP      1 2

Explanation

setDT()通过引用将data.frame转换为data.table,即无需复制。

CJ()是一个交叉联盟。它从载体的叉积形成data.table。因此,它是data.table版本的expand.grid。参数unique = TRUE是在level()unique()中包装每个参数的一种方便的替代方法。

按组计数是用dt[, .N, keyby = c("variables", "group", "values")]完成的:

   variables group values N
1:       sex  DOWN      0 1
2:       sex  DOWN      1 1
3:       sex    UP      1 2
4:     smoke  DOWN      0 1
5:     smoke  DOWN      1 1
6:     smoke    UP      0 1
7:     smoke    UP      1 1
8:     sport  DOWN      1 2
9:     sport    UP      1 2

现在,dt[, .N, keyby = c("variables", "group", "values")][cj](右)加入CJ()结果与所有可能的组合。

最后,[is.na(N), N := 0]NA替换了N列中的所有0s。


1
投票

你也可以这样做:

library(plyr)
d1 <- count(df, c("variables", "group", "values"))
d2 <- expand.grid(list(levels(df$variables), levels(df$group), levels(df$values)))
d2$freq <- 0
colnames(d2) <- colnames(d1)
m <- merge(d1, d2, by = c("variables", "group", "values"), all.y  = T)[,-5]
m[is.na(m)] <- 0

   # variables group values freq.x
# 1        sex  DOWN      0      1
# 2        sex  DOWN      1      1
# 3        sex    UP      0      0
# 4        sex    UP      1      2
# 5      smoke  DOWN      0      1
# 6      smoke  DOWN      1      1
# 7      smoke    UP      0      1
# 8      smoke    UP      1      1
# 9      sport  DOWN      0      0
# 10     sport  DOWN      1      2
# 11     sport    UP      0      0
# 12     sport    UP      1      2

我们的想法是制作一个数据框(名为d2),其中生成variablesgroup以及values的所有可能组合,然后将其与d1合并。


0
投票

这是一个想法。您可以基于freq变量复制行。如果freq为2,则复制的行将具有唯一的rowname,我们可以将其定位并将其freqvalues更改为0。

df1 <- plyr::count(df, c("variables", "group", "values"))
df2 <- df1[rep(row.names(df1), df1$freq),]
df2$freq[grep('.', row.names(df2), fixed = TRUE)] <- 0
df2$values[df2$freq == 0] <- 0

df2
#     variables group values freq
#1         sex  DOWN      0    1
#2         sex  DOWN      1    1
#3         sex    UP      1    2
#3.1       sex    UP      0    0
#4       smoke  DOWN      0    1
#5       smoke  DOWN      1    1
#6       smoke    UP      0    1
#7       smoke    UP      1    1
#8       sport  DOWN      1    2
#8.1     sport  DOWN      0    0
#9       sport    UP      1    2
#9.1     sport    UP      0    0

如果你想重置你的rownames那么,row.names(df2) <- NULL

© www.soinside.com 2019 - 2024. All rights reserved.