计算所有观察到的因子水平,包括未观察到的因子水平
Count all observed factor levels, also those that aren't observed
我们有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
如何实现上面的输出?
这是一个想法。您可以根据 freq
变量复制行。如果频率为 2,那么复制的行将有一个唯一的行名,我们可以将其作为目标并将其 freq
和 values
更改为 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
如果你想重置你的行名,
row.names(df2) <- NULL
你也可以这样做:
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
),其中生成variables
和group
和values
的所有可能组合,然后合并它d1
.
您也可以使用 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
说明
setDT()
通过引用 将 data.frame
转换为 data.table
,即不进行复制。
CJ()
是交叉连接。它根据向量的叉积形成 data.table
。因此,它是 expand.grid
的 data.table
版本。
参数 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]
将 N
列中的所有 NA
替换为 0
。
我们有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
如何实现上面的输出?
这是一个想法。您可以根据 freq
变量复制行。如果频率为 2,那么复制的行将有一个唯一的行名,我们可以将其作为目标并将其 freq
和 values
更改为 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
如果你想重置你的行名,
row.names(df2) <- NULL
你也可以这样做:
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
),其中生成variables
和group
和values
的所有可能组合,然后合并它d1
.
您也可以使用 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
说明
setDT()
通过引用 将 data.frame
转换为 data.table
,即不进行复制。
CJ()
是交叉连接。它根据向量的叉积形成 data.table
。因此,它是 expand.grid
的 data.table
版本。
参数 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]
将 N
列中的所有 NA
替换为 0
。