R中两组观察值的条形图总和

Barplot sum of observations in two groups in R

我有以下形式的数据:

mydata <- data.frame(test = 1:20, group = sample(c("A", "B"), 20, rep=TRUE), var1 = sample(c("yes", "no", "NA"), 20, rep=TRUE), var2 = sample(c("yes", "no", "NA"), 20, rep=TRUE), var3 = sample(c("yes", "no", "NA"), 20, rep=TRUE), var4 = sample(c("yes", "no", "NA"), 20, rep=TRUE), var5 = sample(c("yes", "no", "NA"), 20, rep=TRUE))

我想制作一个条形图,在其中比较 A 组和 B 组的观察次数(频率计数),它们具有 0 "yes" 个条目、1 个 "yes" 个条目、2 "yes" 条目一直到所有 5 个变量都是 "yes"。最终结果将是一个条形图,其中 X 轴显示所有可能的 "yes" 条目数 (0,1,2,3,4,5),Y 轴显示计数频率和组的单独条形图每个 X 值的 A 和 B。每个组的频率计数(条形高度)是具有给定数量 "yes" 条目的行数。缺失数据 (NA) 计为 "No"。看了其他帖子,还是不太清楚这个怎么写,顶一下。

尝试

library(ggplot2)
library(dplyr)
library(tidyr)
f1 <- function(x) sum(x=='yes')

mydata %>% 
      group_by(group) %>% 
      summarise_each(funs(f1), var1:var5) %>% 
      gather(Var, Val, var1:var5)%>%
      ggplot(., aes(x=Var, y=Val, fill=group))+
      geom_bar(stat="identity", position='dodge')

更新

根据@Math post 上的评论,也许这有帮助

 df1 <-  gather(mydata, Var, Val, var1:var5) %>%
                   group_by(group, test) %>%
                   summarise(Val=sum(Val=='yes')) %>% 
                   group_by(group, Val) %>% 
                   summarise(n=n())

 left_join(expand.grid(group=unique(df1$group),
        Val= unique(df1$Val)), df1) %>% 
            mutate(n=replace(n, is.na(n), 0))%>%
            ggplot(., aes(x=Val, y=n, fill=group))+
             geom_bar(stat='identity', position='dodge')

barplot 函数接受一个矩阵作为参数,并将根据列对条形进行分组。

您可以在列(第二个参数==2)上使用 apply 生成您想要的矩阵,然后使用 barplot:

绘制
res=apply(as.matrix(mydata[,3:ncol(mydata)]), 2, function(cc) { return(c(sum(mydata$group=="A" & cc=="yes"), sum(mydata$group=="B" & cc=="yes"))) })
barplot(res, beside=T)

编辑 按行申请,思路是一样的,要生成barplot的矩阵。

mydata$count = apply(as.matrix(mydata[3:ncol(mydata)]), 1, 
function(cc) { return(sum(cc=="yes")) })
barmat = c()
for (ii in 1:range(mydata$count)[2]) {
    barmat = cbind(barmat, c(sum(mydata$group=="A" & mydata$count==ii),sum(mydata$group=="B" & mydata$count==ii) ))
}
colnames(barmat) = 1:range(mydata$count)[2]
barplot(barmat, beside=T)