R 交叉列表多回答问题
我需要通过一个分组变量交叉列出多个响应(存储为一组变量)。我的调查问题是:“你吃过以下哪种水果?”然后,来自地理区域1或区域2的受访者会得到一份标有“1.橙色,2.芒果,…”的列表,并且从是(1)或否(0)问题得出的结果数据是:R 交叉列表多回答问题,r,dplyr,R,Dplyr,我需要通过一个分组变量交叉列出多个响应(存储为一组变量)。我的调查问题是:“你吃过以下哪种水果?”然后,来自地理区域1或区域2的受访者会得到一份标有“1.橙色,2.芒果,…”的列表,并且从是(1)或否(0)问题得出的结果数据是: set.seed(1) df <- data.frame(area=rep(c('Area 1','Area 2'), each=6), var_orange=sample(0:1, 12, T),
set.seed(1)
df <- data.frame(area=rep(c('Area 1','Area 2'), each=6),
var_orange=sample(0:1, 12, T),
var_banana=sample(0:1, 12, T),
var_melon=sample(0:1, 12, T),
var_mango=sample(0:1, 12, T))
area var_orange var_banana var_melon var_mango
1 Area 1 0 1 0 1
2 Area 1 0 0 0 0
3 Area 1 1 1 0 1
4 Area 1 1 0 0 0
5 Area 1 0 1 1 1
6 Area 1 1 1 0 1
7 Area 2 1 0 0 1
8 Area 2 1 1 1 1
9 Area 2 1 1 0 1
10 Area 2 0 0 0 1
11 Area 2 0 1 1 0
12 Area 2 0 0 1 0
我发现了一个与multfreqtable函数相关的函数,该函数为我的数据提供单向摘要:
multfreqtable = function(data, question.prefix) {
z = length(question.prefix)
temp = vector("list", z)
for (i in 1:z) {
a = grep(question.prefix[i], names(data))
b = sum(data[, a] != 0)
d = colSums(data[, a] )
e = sum(rowSums(data[,a]) !=0)
f = as.numeric(c(d, b))
temp[[i]] = data.frame(question = c(sub(question.prefix[i],
"", names(d)), "Total"),
freq = f,
percent_response = (f/b)*100,
percent_cases = round((f/e)*100, 2))
names(temp)[i] = question.prefix[i]
}
temp
}
multfreqtable(df, "var_")
$var_
question freq percent_response percent_cases
1 orange 6 24 54.55
2 banana 7 28 63.64
3 melon 4 16 36.36
4 mango 8 32 72.73
5 Total 25 100 227.27
但我对双向总结感兴趣
我可以使用a中建议的dplyr
,并获得:
但我需要一个更整洁的表格输出,带有边缘列频率 使用
aggregate
的不同解决方案是
T1 = aggregate(df[,2:5], list(df$area), sum)
rownames(T1) = T1[,1]
T1 = t(T1[,-1])
T1 = addmargins(T1, 1:2, FUN = c(Total = sum), quiet=TRUE)
T1
Area 1 Area 2 Total
var_orange 3 3 6
var_banana 4 3 7
var_melon 1 3 4
var_mango 4 4 8
Total 12 13 25
感谢@rawr建议简化使用addmargins
如果希望表格以百分比而不是计数表示,只需除以总计数即可得到分数,然后更改为百分比
T1 = aggregate(df[,2:5], list(df$area), sum)
rownames(T1) = T1[,1]
T1 = t(T1[,-1])
T1 = T1 * 100 / sum(T1)
T1 = addmargins(T1, FUN = c(Total = sum), quiet=TRUE)
T1
Area 1 Area 2 Total
var_orange 12 12 24
var_banana 16 12 28
var_melon 4 12 16
var_mango 16 16 32
Total 48 52 100
使用
aggregate
的另一种解决方案是
T1 = aggregate(df[,2:5], list(df$area), sum)
rownames(T1) = T1[,1]
T1 = t(T1[,-1])
T1 = addmargins(T1, 1:2, FUN = c(Total = sum), quiet=TRUE)
T1
Area 1 Area 2 Total
var_orange 3 3 6
var_banana 4 3 7
var_melon 1 3 4
var_mango 4 4 8
Total 12 13 25
感谢@rawr建议简化使用addmargins
如果希望表格以百分比而不是计数表示,只需除以总计数即可得到分数,然后更改为百分比
T1 = aggregate(df[,2:5], list(df$area), sum)
rownames(T1) = T1[,1]
T1 = t(T1[,-1])
T1 = T1 * 100 / sum(T1)
T1 = addmargins(T1, FUN = c(Total = sum), quiet=TRUE)
T1
Area 1 Area 2 Total
var_orange 12 12 24
var_banana 16 12 28
var_melon 4 12 16
var_mango 16 16 32
Total 48 52 100
您可以首先使用
dplyr
计算值,然后使用knitr::kable
等工具将其放入表格中
library(dplyr)
library(knitr)
set.seed(1)
df <- data.frame(area = rep(c('Area 1','Area 2'), each = 6),
var_orange = sample(0:1, 12, T),
var_banana = sample(0:1, 12, T),
var_melon = sample(0:1, 12, T),
var_mango = sample(0:1, 12, T))
t1 <- df %>% group_by(area) %>% summarise_each(funs(mean))
t2 <- df %>% summarise_each(funs(mean))
kable(rbind(t1, t2))
要进一步优化输出以模仿Stata的输出,请执行以下操作:
polished <- 100 * rbind(t1, t2) %>% # Use percentages
select(-area) %>% # Drop "area"
mutate(Total = rowSums(.[])) %>% # Add Total
as.matrix %>% t
kable(polished, digits = 2, col.names = c("Area 1", "Area 2", "Total"))
您可以首先使用
dplyr
计算值,然后使用knitr::kable
等工具将其放入表格中
library(dplyr)
library(knitr)
set.seed(1)
df <- data.frame(area = rep(c('Area 1','Area 2'), each = 6),
var_orange = sample(0:1, 12, T),
var_banana = sample(0:1, 12, T),
var_melon = sample(0:1, 12, T),
var_mango = sample(0:1, 12, T))
t1 <- df %>% group_by(area) %>% summarise_each(funs(mean))
t2 <- df %>% summarise_each(funs(mean))
kable(rbind(t1, t2))
要进一步优化输出以模仿Stata的输出,请执行以下操作:
polished <- 100 * rbind(t1, t2) %>% # Use percentages
select(-area) %>% # Drop "area"
mutate(Total = rowSums(.[])) %>% # Add Total
as.matrix %>% t
kable(polished, digits = 2, col.names = c("Area 1", "Area 2", "Total"))
您可以从
?table
、?prop.table
和?addmargins
开始。示例输出中最下面的一行是sums,而最右边的一列是averages。这种不一致性使问题更加复杂。您可以从?table
、?prop.table
和?addmargins
开始。示例输出中最下面的一行是sums,而最右边的一列是averages。这种不一致性使问题更加复杂。addmargins
可用于T1
,addmargins(T1,1:2,FUN=c(Total=sum))
@rawr这是一个真正的改进。您介意我将其添加到我的解决方案中吗?@rawr看起来不错,但将表格值作为单元格百分比会更好。@amo将矩阵除以总数T1/25*100
@G5W听起来不错,试试看addmargins
可以在T1
上使用,addmargins(T1,1:2,FUN=c(total=sum))
@rawr这是一个真正的进步。您介意我将其添加到我的解决方案中吗?@rawr看起来不错,但将表格值作为单元格百分比会更好。@amo将矩阵除以总数T1/25*100
@G5W听起来不错,可以这样做,但summary_each()
会因应用mean()而引发警告
在非数字区域列上。要解决此问题,可以通过t2%summary_each(funs(mean))
限制函数仅作用于数字列。另一个问题是结果第三行的“NA”。我用t2$area@amo替换了“Total”,当然,我已经修改了我的答案来模仿Stata输出。我宁愿忽略警告并保留NA,这样就可以简单地rbind t1和t2。我注意到kable(抛光,align='c',digits=2,format=“pandoc”,caption=“表格标题”)
使输出更漂亮。可能值得添加?它可以工作,但在非数字区域列上应用mean()
会引发警告。要解决此问题,可以通过t2%summary_each(funs(mean))
限制函数仅作用于数字列。另一个问题是结果第三行的“NA”。我用t2$area@amo替换了“Total”,当然,我已经修改了我的答案来模仿Stata输出。我宁愿忽略警告并保留NA,这样就可以简单地rbind t1和t2。我注意到kable(抛光,align='c',digits=2,format=“pandoc”,caption=“表格标题”)
使输出更漂亮。也许值得补充一下?