R 在ggplot2中叠加/叠加分组条形图

R 在ggplot2中叠加/叠加分组条形图,r,ggplot2,R,Ggplot2,我想做一个条形图,展示两个时间点“之前”和“之后”的数据叠加 在每个时间点,参与者被问到两个问题(“疼痛”和“恐惧”),他们会回答1分、2分或3分 我现有的代码很好地绘制了“before”时间点的数据计数,但我似乎无法添加“after”数据的计数 这是我希望添加“after”数据的绘图的草图,黑色条表示“after”数据: 我想在ggplot2()中进行绘图,并且我已经尝试从中改编代码,但无法使其用于分组数据 非常感谢 #DATA PREP library(dplyr) library(ggp

我想做一个条形图,展示两个时间点“之前”和“之后”的数据叠加

在每个时间点,参与者被问到两个问题(“疼痛”和“恐惧”),他们会回答1分、2分或3分

我现有的代码很好地绘制了“before”时间点的数据计数,但我似乎无法添加“after”数据的计数

这是我希望添加“after”数据的绘图的草图,黑色条表示“after”数据:

我想在ggplot2()中进行绘图,并且我已经尝试从中改编代码,但无法使其用于分组数据

非常感谢

#DATA PREP
library(dplyr)
library(ggplot2)
library(tidyr)


df <- data.frame(before_fear=c(1,1,1,2,3),before_pain=c(2,2,1,3,1),after_fear=c(1,3,3,2,3),after_pain=c(1,1,2,3,1))


df <- df %>% gather("question", "answer_option") # Get the counts for each answer of each question 
df2 <- df  %>%
  group_by(question,answer_option) %>%
  summarise (n = n()) 
df2 <- as.data.frame(df2)


df3 <- df2 %>% mutate(time = factor(ifelse(grepl("before", question), "before", "after"),
                                        c("before", "after"))) # change classes and split data into two data frames
df3$n <- as.numeric(df3$n)
df3$answer_option <- as.factor(df3$answer_option)
df3after <- df3[ which(df3$time=='after'), ]
df3before <- df3[ which(df3$time=='before'), ]


# CODE FOR 'BEFORE' DATA ONLY PLOT - WORKS  
    ggplot(df3before, aes(fill=answer_option, y=n, x=question)) + geom_bar(position="dodge", stat="identity")



# CODE FOR 'BEFORE' AND 'AFTER' DATA PLOT - DOESN'T WORK
ggplot(mapping = aes(x, y,fill)) +
  geom_bar(data = data.frame(x = df3before$question, y = df3before$n, fill= df3before$index_value), width = 0.8, stat = 'identity') +
  geom_bar(data = data.frame(x = df3after$question, y = df3after$n, fill=df3after$index_value), width = 0.4, stat = 'identity', fill = 'black') +
  theme_classic() + scale_y_continuous(expand = c(0, 0))
#数据准备
图书馆(dplyr)
图书馆(GG2)
图书馆(tidyr)
df%
总结(n=n())
df2我认为线索是设置“after”条的
宽度
,但要避开它们,就好像它们的宽度是0.9(即与“before”条相同的(默认)宽度)。此外,由于我们没有映射“after”栏的
填充
,因此我们需要使用
美学来实现回避

我更喜欢只使用一个数据集,并在每次调用
geom\u col
时将其子集

ggplot(mapping = aes(x = question, y = n, fill = factor(ans))) +
  geom_col(data = d[d$t == "before", ], position = "dodge") +
  geom_col(data = d[d$t == "after", ], aes(group = ans),
           fill = "black", width = 0.5, position = position_dodge(width = 0.9))
数据:

预先计算计数,并按上述操作进行
geom\u col

# d2 <- d[ , .N, by = .(question, ans)]

数据:


df我的解决方案与@Henrik的非常相似,但我想指出几点

首先,您正在
geom\u col
s中构建数据帧,这可能比您需要的更混乱。如果您已经创建了
df3after
等,那么您最好在
ggplot
中使用它

其次,我很难跟上你的整理工作。我认为有两个
tidyr
函数可以让您更轻松地完成这项任务,因此我采用了不同的方法,例如使用
separate
创建
time
measure
列,而不是手动搜索它们,从而使其更具可扩展性。这也可以让你在x轴上放置“痛苦”和“恐惧”,而不是仍然有“之前的痛苦”和“之前的恐惧”,一旦你在绘图上有了“之后”值,它们就不再是准确的表示。但是你可以无视这一点,坚持你自己的方法

库(tidyverse)
df%
变异(答案选项=as.因子(答案选项))%>%
计数(问题、答案选项)%>%
分开(问题,分为=c(“时间”,“测量”),sep=“”,remove=F)
德福朗
#>#tibble:12 x 5
#>问题时间测量答案选项n
#>                         
#>一个接一个的恐惧
#>一次又一次的恐惧2 1
#>一次又一次的恐惧
#>4后痛后痛1 3
#>5后痛后痛2 1
#>6术后疼痛3 1
#>7先于恐惧1先于恐惧3
#>先恐惧后恐惧2 1
#>9在恐惧之前3 1
#>10先于痛1先于痛2
#>11前痛2前痛2
#>12前痛3前痛1
正如您所做的,我将其拆分为前后数据集,然后用2
geom_col
s绘制它们。我仍然将
df_long
放入
ggplot
,几乎将其视为一个假人,以获得统一的x和y美学效果。就像@Henrik所说的,你可以在
geom_col
和它的
position_dodge
中使用不同的
width
来避开宽度为90%的栅栏,但栅栏本身的宽度只有40%

df_在%filter之前(时间==“之前”)
百分比过滤器后的df_(时间=“之后”)
ggplot(df_long,aes(x=measure,y=n))+
地理坐标(aes(填充=回答选项),
数据=之前的df_,宽度=0.9,
位置=位置\减淡(宽度=0.9))+
地理坐标(aes(组=答案选项),
数据=df_后,填充=“黑色”,宽度=0.4,
位置=位置\减淡(宽度=0.9))

您可以在每个
geom\u col
内部进行过滤,而不是制作两个单独的数据帧。这通常是我的偏好,除非过滤更复杂。此代码将获得与上面相同的绘图

ggplot(df_long,aes(x=measure,y=n))+
地理坐标(aes(填充=回答选项),
数据=.%>%过滤器(时间=“之前”),宽度=0.9,
位置=位置\减淡(宽度=0.9))+
地理坐标(aes(组=答案选项),
数据=.%>%过滤器(时间=“之后”),填充=“黑色”,宽度=0.4,
位置=位置\减淡(宽度=0.9))
library(data.table)
d <- melt(setDT(df), measure.vars = names(df), value.name = "ans")
d[ , c("t", "question") := tstrsplit(variable, "_")]
# d2 <- d[ , .N, by = .(question, ans)]
ggplot(mapping = aes(x = question, fill = factor(ans))) +
  geom_bar(data = d[d$t == "before", ], position = "dodge") +
  geom_bar(data = d[d$t == "after", ], aes(group = ans),
           fill = "black", width = 0.5, position = position_dodge(width = 0.9))
df <- data.frame(before_fear = c(1,1,1,2,3), before_pain = c(2,2,1,3,1),
                     after_fear = c(1,3,3,2,3),after_pain = c(1,1,2,3,1))