R中的双向列联表
我有一个数据框,我想从两列中输出一个双向列联表。他们都有价值“太少”,“关于正确”或“太多”。R中的双向列联表
我打字
df %>%
filter(!is.na(col1)) %>%
group_by(col1) %>%
summarise(count = n())
分别为二者的和得到的东西是这样的:
col1 count
<fctr> <int>
Too Little 19259
About Right 9539
Too Much 2816
我想实现的是:
Too Little About Right Too Much Total
col1 19259 9539 2816 31614
col2 20619 9374 2262 32255
Total 39878 18913 5078 63869
我一直试图使用表功能
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
我给tabulate
一试,这是table
基础(见?tabulate
)是什么。例如,给定
set.seed(123)
vals <- LETTERS[1:3]
df <- as.data.frame(replicate(3, sample(vals, 5, T)))
df <- data.frame(lapply(df, "levels<-", vals))
那么你可以做
m <- t(sapply(df, tabulate, nbins = length(vals)))
colnames(m) <- vals
addmargins(m)
# A B C Sum
# V1 1 1 3 5
# V2 1 3 1 5
# V3 1 2 2 5
# Sum 3 6 6 15
或(通过@thelatemail)刚刚
addmargins(t(sapply(df, 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
我不知道为什么你需要'tabulate'具体。只是'addmargins(t(sapply(df,table))''会做到这一点,并且会保留这些名字。 – thelatemail
@thelatemail真的,谢谢,我补充了这一点(尽管它可能与zx8754的解决方案太相似了,现在...) – lukeA
不管怎样,做'sapply'比简单地列出一个列表更简单 – thelatemail
我们可以在一个循环,然后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
无论如何,它的速度肯定会更快,但是你的基准会遗漏'vals '并不总是提前知道(或者至少不应该被认为是已知的),所以你必须在那里查找'vals thelatemail
@ thelatemail真的,也许它应该是'vals zx8754
那么什么是有望走出把你想要 – Wen
欢迎喜来所以,提问在[mimimal但完整的(很重要https://stackoverflow.com/help/ mcve)形式。也总是试图包含一些示例数据(截至目前没有人,但你可以看到'df')也许只有几行就足以作为一个简单的例子 – Nate