AW27
AW27

Reputation: 505

Grouped and Stacked Barplot in R

I currently have two distinct data frames:

dput(df1)
structure(list(n = c("0", "0.01", "0.02", "0.03", "0.04", "0.05", 
"0.06", "0.07", "0.08", "0.09", "0.1", "0", "0.01", "0.02", "0.03", 
"0.04", "0.05", "0.06", "0.07", "0.08", "0.09", "0.1"), Condition = c("Correct", 
"Correct", "Correct", "Correct", "Correct", "Correct", "Correct", 
"Correct", "Correct", "Correct", "Correct", "Incorrect", "Incorrect", 
"Incorrect", "Incorrect", "Incorrect", "Incorrect", "Incorrect", 
"Incorrect", "Incorrect", "Incorrect", "Incorrect"), Value = c(100, 
100, 98, 84, 77, 36, 1, 0, 0, 0, 0, 0, 0, 2, 16, 23, 64, 99, 
100, 100, 100, 100), Method = c("Method1", "Method1", "Method1", 
"Method1", "Method1", "Method1", "Method1", "Method1", "Method1", 
"Method1", "Method1", "Method1", "Method1", "Method1", "Method1", 
"Method1", "Method1", "Method1", "Method1", "Method1", "Method1", 
"Method1")), row.names = c(NA, -22L), class = "data.frame")


dput(df2)
structure(list(n = c("0", "0.01", "0.02", "0.03", "0.04", "0.05", 
"0.06", "0.07", "0.08", "0.09", "0.1", "0", "0.01", "0.02", "0.03", 
"0.04", "0.05", "0.06", "0.07", "0.08", "0.09", "0.1"), Condition = c("Correct", 
"Correct", "Correct", "Correct", "Correct", "Correct", "Correct", 
"Correct", "Correct", "Correct", "Correct", "Incorrect", "Incorrect", 
"Incorrect", "Incorrect", "Incorrect", "Incorrect", "Incorrect", 
"Incorrect", "Incorrect", "Incorrect", "Incorrect"), Value = c(100, 
100, 92, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 66, 100, 100, 100, 
100, 100, 100, 100), Method = c("Method2", "Method2", "Method2", 
"Method2", "Method2", "Method2", "Method2", "Method2", "Method2", 
"Method2", "Method2", "Method2", "Method2", "Method2", "Method2", 
"Method2", "Method2", "Method2", "Method2", "Method2", "Method2", 
"Method2")), row.names = c(NA, -22L), class = "data.frame")

I am trying to develop a grouped, stacked barplot where n is on the x-axis, with stacked bars for Condition, grouped by Method, and having Value on the y-axis. So far, I have been able to develop a DataFrame only having Condition == 'Correct', but am trying to fill the bars completely to 100.

I asked this question previously but don't think I explained it well enough, but am still struggling to develop the result for the problem.

Thanks in advance.

Upvotes: 1

Views: 85

Answers (2)

jay.sf
jay.sf

Reputation: 73802

You could rbind the data, reshape, and use barplot.

rbind(df1, df2) |>
  transform(g=paste0(Condition, Method)) |>
  (\(.) .[c('n', 'Value', 'g')])() |> 
  reshape(direction="wide", idvar="n", timevar="g") |>
  (\(.) as.matrix(.[-1]))() |> 
  barplot(col=hcl.colors(11), legend.text=head(df1$n, 11), cex.names=.9,
          args.legend=list(x='topleft', ncol=2, cex=.8, title='n'), 
          main='My Plot') 

Note: R >= 4.1 used.

enter image description here

Upvotes: 1

Rui Barradas
Rui Barradas

Reputation: 76673

To stack the bars by Condition filling to 100% use position_fill(). And facet_wrap to group by Method.

df3 <- rbind(df1, df2)

ggplot(df3, aes(n, Value, fill = Condition)) +
  geom_col(position = position_fill()) +
  facet_wrap( ~ Method) 

enter image description here


Edit

Inspired in this answer, the following plots each data set df1 and df2 and uses interaction to create 4 color names.

df1$n <- as.numeric(df1$n)
df2$n <- as.numeric(df2$n)
barwidth <- 0.0035

fac <- with(rbind(df1, df2), interaction(Method, Condition, sep = ": "))
fill_colors <- c("#008dca", "#d70000", "#00405b", "#7d0000")
fill_colors <- setNames(fill_colors, levels(fac))

ggplot() +
  geom_bar(
    data = df1,
    mapping = aes(x = n, 
                  y = Value, fill = interaction(Method, Condition, sep = ": ")),
    stat = "identity",
    color = "white",
    width = barwidth,
    position = position_fill()
  ) +
  geom_bar(
    data = df2,
    mapping = aes(x = n + barwidth + 0.0001, 
                  y = Value, fill = interaction(Method, Condition, sep = ": ")),
    stat = "identity",
    color = "white",
    width = barwidth,
    position = position_fill()
  ) +
  scale_x_continuous(breaks = unique(df1$n) + barwidth/2, labels = unique(df1$n)) +
  scale_fill_manual(values = fill_colors) +
  guides(fill = guide_legend(title = "Method")) +
  theme_bw()

enter image description here

Upvotes: 1

Related Questions