这不使用任何包,只有一行。这里DF$Group[row(DF[-1])] 是一个组标签向量,每个元素对应于解开的数字向量unlist(DF[-1])。
table(DF$Group[row(DF[-1])], unlist(DF[-1]))
给予:
1 2 3 4
DEF 3 1 3 1
PQR 2 2 1 1
XYZ 2 2 1 1
如果问题中显示的行和列的顺序很重要,那么我们可以从两个 table 参数中的每一个创建因子,并按照所需的顺序定义因子级别。在这种情况下,我们使用以下代码行而不是上面的代码行:
table(Group = factor(DF$Group[row(DF[-1])], unique(DF$Group)), factor(unlist(DF[-1]), 4:1))
给予:
Group 4 3 2 1
XYZ 1 1 2 2
DEF 1 3 1 3
PQR 1 1 2 2
上面产生了一个"table"类的对象。这是一个特别适合列表频率的类别。例如,一旦在这种形式中,ftable 可以用来轻松地重新排列它,如ftable(tab, row.vars = 2) 或ftable(tab, row.vars = 1:2) 其中tab 是上面的计算表。
如果首选 data.frame,则将其转换为:
cbind(Group = rownames(tab), as.data.frame.matrix(tab))
输入 data.frame DF 在最后的注释 2 中可重复地定义。
替代品
虽然上面看起来是最直接的,但这里还有一些其他的不使用包的替代方案:
1) by 对于具有相同Group 值的每组行,匿名函数创建一个标识组的data.frame,将除第一列之外的列转换为具有指示的因子水平并运行table 以获取计数。返回的"by" 列表重新排序为原始顺序,我们将rbind 全部重新组合在一起。
do.call("rbind",
by(DF, DF$Group, function(x) {
data.frame(Group = x[1,1],
as.list(table(factor(unlist(x[, -1]), levels = 4:1))),
check.names = FALSE)
})[unique(DF$Group)])
给予:
Group 4 3 2 1
XYZ XYZ 1 1 2 2
DEF DEF 1 3 1 3
PQR PQR 1 1 2 2
1a) 这个稍微短一点的变体也可以。它返回一个使用行名标识组的矩阵。
kount <- function(x) table(factor(unlist(x), levels = 4:1))
m <- do.call("rbind", by(DF[, -1], DF$Group, kount)[unique(DF$Group)])
给予:
> m
4 3 2 1
XYZ 1 1 2 2
DEF 1 3 1 3
PQR 1 1 2 2
2) 外层
gps <- unique(DF$Group)
levs <- 4:1
kount2 <- function(g, lv) sum(subset(DF, Group == g)[-1] == lv, na.rm = TRUE)
m <- outer(gps, levs, Vectorize(kount2))
dimnames(m) <- list(gps, levs))
给出这个矩阵:
> m
4 3 2 1
XYZ 1 1 2 2
DEF 1 3 1 3
PQR 1 1 2 2
3) 应用
kount3 <- function(g) table(factor(unlist(DF[DF$Group == g, -1]), levels = 4:1))
gps <- as.character(unique(DF$Group))
do.call("rbind", sapply(gps, kount3, simplify = FALSE))
给予:
4 3 2 1
XYZ 1 1 2 2
DEF 1 3 1 3
PQR 1 1 2 2
4) 聚合
aggregate(1:nrow(DF), DF["Group"], function(ix)
table(factor(unlist(DF[ix, -1]), levels = 4:1)))[unique(DF$Group), ]
给予:
Group x.4 x.3 x.2 x.1
3 XYZ 1 1 2 2
1 DEF 1 3 1 3
2 PQR 1 1 2 2
5) 点按
do.call("rbind", tapply(1:nrow(DF), DF$Group, function(ix)
table(factor(unlist(DF[ix, -1]), levels = 4:1))))[unique(DF$Group), ]
6) 重塑
with(reshape(DF, dir = "long", varying = list(2:5)),
table(factor(Group, unique(DF$Group)), factor(A, 4:1)))
给予:
4 3 2 1
XYZ 1 1 2 2
DEF 1 3 1 3
PQR 1 1 2 2
注 1: (1a)、(2)、(3)、(5) 和 (6) 生成以组为行名的矩阵或表格结果。如果您更喜欢以 Groups 为列的数据框,那么假设 m 是矩阵,请添加以下内容:
data.frame(Group = rownames(m), m, check.names = FALSE)
注2:输入DF的可复现形式为:
Lines <- "Group A B C D
XYZ 4 Na 1 3
XYZ Na 2 2 1
DEF 4 3 2 1
DEF 3 3 1 1
PQR 1 Na Na 1
PQR 3 2 2 4"
DF <- read.table(text = Lines, header = TRUE, na.strings = "Na")