R中的双向列联表
我有一个dataframe,我想从两列中输出一个双向列联表。他们都有“太少”、“差不多正确”或“太多”的价值观 我在打字R中的双向列联表,r,two-way,contingency,R,Two Way,Contingency,我有一个dataframe,我想从两列中输出一个双向列联表。他们都有“太少”、“差不多正确”或“太多”的价值观 我在打字 df %>% filter(!is.na(col1)) %>% group_by(col1) %>% summarise(count = n()) 分别为这两种类型,并获得如下内容: col1 count <fctr> <int> Too Little 19259 Abou
df %>%
filter(!is.na(col1)) %>%
group_by(col1) %>%
summarise(count = n())
分别为这两种类型,并获得如下内容:
col1 count
<fctr> <int>
Too Little 19259
About Right 9539
Too Much 2816
我一直在尝试使用table函数
addmargins(table(df$col1, df$col2))
但结果不是我想要的
Too Little About Right Too Much Sum
Too Little 13770 4424 740 18934
About Right 4901 3706 700 9307
Too Much 1250 800 679 2729
Sum 19921 8930 2119 30970
我会给出<代码>表格>代码>一个尝试,这是<代码>表< /代码>的基础(参见<代码>表制表< /代码>)。举个例子
set.seed(123)
vals <- LETTERS[1:3]
df <- as.data.frame(replicate(3, sample(vals, 5, T)))
df <- data.frame(lapply(df, "levels<-", vals))
我会给出<代码>表格>代码>一个尝试,这是<代码>表< /代码>的基础(参见<代码>表制表< /代码>)。举个例子
set.seed(123)
vals <- LETTERS[1:3]
df <- as.data.frame(replicate(3, sample(vals, 5, T)))
df <- data.frame(lapply(df, "levels<-", vals))
我们可以在循环中使用table,然后使用rbind:
# Using dummy data from @lukeA's answer
addmargins(do.call(rbind, lapply(df1, table)))
# A B C Sum
# V1 1 1 3 5
# V2 1 3 1 5
# V3 1 2 2 5
# Sum 3 6 6 15
基准测试
# bigger data
set.seed(123)
vals <- LETTERS[1:20]
df1 <- as.data.frame(replicate(20, sample(vals, 100000, T)))
df1 <- data.frame(lapply(df1, "levels<-", vals))
microbenchmark::microbenchmark(
lukeA = {
m1 <- t(sapply(df1, tabulate, nbins = length(vals)))
colnames(m1) <- vals
m1 <- addmargins(m1)
},
# as vals only used for luke's solution, keep it in.
lukeA_1 = {
vals <- LETTERS[1:20]
m2 <- t(sapply(df1, tabulate, nbins = length(vals)))
colnames(m2) <- vals
m2 <- addmargins(m2)
},
thelatemail = {m3 <- addmargins(t(sapply(df1, table)))},
zx8754 = {m4 <- addmargins(do.call(rbind, lapply(df1, table)))}
)
# Unit: milliseconds
# expr min lq mean median uq max neval
# lukeA 2.349969 2.371922 2.518447 2.473839 2.558653 3.363738 100
# lukeA_1 2.351680 2.377196 2.523473 2.473839 2.542831 3.459242 100
# thelatemail 38.316506 42.054136 43.785777 42.674912 44.234193 90.287809 100
# zx8754 38.695101 41.979728 44.933602 42.762006 44.244314 110.834292 100
#更大的数据
种子集(123)
VAL我们可以在循环中使用表,然后使用rbind:
# Using dummy data from @lukeA's answer
addmargins(do.call(rbind, lapply(df1, table)))
# A B C Sum
# V1 1 1 3 5
# V2 1 3 1 5
# V3 1 2 2 5
# Sum 3 6 6 15
基准测试
# bigger data
set.seed(123)
vals <- LETTERS[1:20]
df1 <- as.data.frame(replicate(20, sample(vals, 100000, T)))
df1 <- data.frame(lapply(df1, "levels<-", vals))
microbenchmark::microbenchmark(
lukeA = {
m1 <- t(sapply(df1, tabulate, nbins = length(vals)))
colnames(m1) <- vals
m1 <- addmargins(m1)
},
# as vals only used for luke's solution, keep it in.
lukeA_1 = {
vals <- LETTERS[1:20]
m2 <- t(sapply(df1, tabulate, nbins = length(vals)))
colnames(m2) <- vals
m2 <- addmargins(m2)
},
thelatemail = {m3 <- addmargins(t(sapply(df1, table)))},
zx8754 = {m4 <- addmargins(do.call(rbind, lapply(df1, table)))}
)
# Unit: milliseconds
# expr min lq mean median uq max neval
# lukeA 2.349969 2.371922 2.518447 2.473839 2.558653 3.363738 100
# lukeA_1 2.351680 2.377196 2.523473 2.473839 2.542831 3.459242 100
# thelatemail 38.316506 42.054136 43.785777 42.674912 44.234193 90.287809 100
# zx8754 38.695101 41.979728 44.933602 42.762006 44.244314 110.834292 100
#更大的数据
种子集(123)
那么你希望得到什么呢?欢迎来到这里,以一种形式提问是很重要的。此外,请始终尝试包含一些示例数据(目前没有人,但您可以看到df
),也许只有几行就足以作为一个最小的示例。因此,您希望得到什么样的结果?欢迎使用,因此,以表格形式提问很重要。另外,请始终尝试包含一些示例数据(目前没有人,但您可以看到df
),可能仅几行就足以作为一个最小的示例。我不知道您为什么需要特别的制表。只需addmargins(t(sapply(df,table))
就可以了,并且会保留名称。@最后一封邮件是真的,谢谢。我添加了这个。(虽然它可能与zx8754的解决方案太相似了,但现在…)不,做sapply
比查找列表更简单。@LateMail在我的文章中添加了基准测试,lukeA的解决方案取得了成功,速度快了20倍。我不知道你为什么特别需要tablate
。只需addmargins(t(sapply(df,table))
就可以了,并且可以保留名称。@LateMail是真的,谢谢。我添加了这个。(虽然它可能与zx8754的解决方案太相似了,但现在…)不,做sapply
比rbind一个列表更简单。@最近的邮件在我的帖子中添加了基准测试,lukeA的解决方案比这快了20倍。无论如何它肯定更快,但你的基准测试忽略了一个事实,vals
并不总是提前知道的(或者至少不应该被认为是已知的)。所以你必须抛弃一个vals@thelatemail True,也许它甚至应该是vals,不管怎样它肯定更快,但是你的基准测试忽略了一个事实,vals
并不总是提前知道(或者至少不应该被认为是已知的)所以你必须扔掉一个vals@thelatemail True,也许它甚至应该是vals