创建是/否响应表的有效方法

时间:2019-07-24 00:44:46

标签: r

我有一个数据框,其中包含对26个变量(问题)的二元调查响应(是/否)的数千个响应;每个参与者还具有性别变量(男性/女性)。我想创建一个表格,列出26个问题中每个回答“是”的比例,并分别为男性和女性。

通过使用下面的代码,我可以实现所需的结果,但是当涉及26个变量时,它似乎效率很低。我确信有更好的方法可以执行此操作,也许使用*apply系列函数之一,但是我不确定如何执行此操作,甚至不确定从哪里开始。非常感谢您的帮助。

df <- data.frame(Sex = c(0,1,1,0,1,0,1,1,0,0), Q1 = c(1,1,0,1,0,0,1,1,0,1), 
                                               Q2 = c(0,1,1,0,0,0,1,0,0,0), 
                                               Q3 = c(0,1,0,0,1,1,0,1,0,1))

df$Sex <- factor(df$Sex, levels = c(0, 1), labels = c("Female", "Male"))

table1 <- 100*prop.table(table(df$Q1[df$Sex == "Female"]))
table2 <- 100*prop.table(table(df$Q2[df$Sex == "Female"]))
table3 <- 100*prop.table(table(df$Q3[df$Sex == "Female"]))

m.table <- rbind(table1, table2, table3)
m.table <- m.table[,c(2)]

table4 <- 100*prop.table(table(df$Q1[!df$Sex == "Female"]))
table5 <- 100*prop.table(table(df$Q2[!df$Sex == "Female"]))
table6 <- 100*prop.table(table(df$Q3[!df$Sex == "Female"]))

f.table <- rbind(table4, table5, table6)
f.table <- f.table[,c(2)]

mf.table <- cbind(m.table, f.table)

3 个答案:

答案 0 :(得分:2)

由于您的回答是“ 1/0”,因此我们可以回答mean个问题列。在基数R中,我们可以使用aggregate

aggregate(.~Sex, df, mean)

#  Sex  Q1  Q2  Q3
#1   0 0.6 0.0 0.4
#2   1 0.6 0.6 0.6

使用dplyr的一种方法是去group_by Sex并通过取mean各个问题列来计算1的比率

library(dplyr)

df %>%
  group_by(Sex) %>%
  summarise_at(vars(starts_with("Q")), mean)


#    Sex    Q1    Q2    Q3
#  <dbl>  <dbl> <dbl> <dbl>
#1     0   0.6   0     0.4
#2     1   0.6   0.6   0.6

或者使用tidyr并进行一些重塑

library(dplyr)
library(tidyr)

df %>%
   gather(question, value, -Sex) %>%
   group_by(Sex, question) %>%
   summarise(yesratio = mean(value)) %>%
   spread(question, yesratio)

答案 1 :(得分:1)

另一种解决方案(不一定比@RonakShah的解决方案更干净):将数据从宽到长整形,在所有三列上计算一张表,计算比例,以“是”比例将比例缩放100:

df_m <- reshape2::melt(df,id.vars="Sex", 
                       variable.name="Variable",
                       value.name="Response")
tt1 <- with(df_m,table(Sex,Variable,Response))
tt2 <- prop.table(tt1,margin=c(1,2))
t(tt2[,,"1"]*100)

答案 2 :(得分:1)

我们可以使用by中的base R

by(df[-1], df$Sex, colMeans)
#df$Sex: Female
# Q1  Q2  Q3 
#0.6 0.0 0.4 
------------------------------------------------------------------------------------------------------------ 
#df$Sex: Male
# Q1  Q2  Q3 
#0.6 0.6 0.6 

或者正如OP提到的有效使用,选项为data.table

library(data.table)
setDT(df)[, lapply(.SD, mean), Sex]
#     Sex  Q1  Q2  Q3
#1: Female 0.6 0.0 0.4
#2:   Male 0.6 0.6 0.6