maleta
maleta

Reputation: 423

Interactive faceted rCharts bar graph filled with a third variable (replicate ggplot2 aes(x=var1, fill=var2) + geom_bar + facet_wrap)

I want to make an interactive bar chart of one variable where the bars are filled in by a second variable and faceted by a third variable. I would like to embed it in a slidify deck. I am guessing rCharts is the right tool for this (or would another package be better?).

Here is my data:

df <- data.frame(numbers = rep(1:3, 30),
                 letter = sample(c("A", "B", "C", "D"), 90, replace = TRUE),
                 status = sample(c("good", "bad", "ugly"), 90, replace = TRUE))

I can do this in ggplot2, but I can't make it interactive. I can make this graph (sorry, can't embed):

ggplot(df, aes(letter, fill = status)) + geom_bar() + facet_wrap(.~numbers)

Linked chart

Ideally I would be able to select and deselect "status" and see the bars change. I've played with the bar chart code on this page but can't make it work. Is this functionality possible?

Upvotes: 1

Views: 223

Answers (2)

Jon Nagra
Jon Nagra

Reputation: 1660

I was a heavy rCharts user, but nowadays, in my opinion, plotly is a better supported option (rCharts is not in CRAN anymore).

Furthermoreplotly has an automatic way to make ggplot2 charts interactive. For your example:

library(ggplot2)
library(plotly)
df <- data.frame(
  numbers = rep(1:3, 30),
  letter = sample(c("A", "B", "C", "D"), 90, replace = TRUE),
  status = sample(c("good", "bad", "ugly"), 90, replace = TRUE)
)

p <-
  ggplot(df, aes(letter, fill = status)) + geom_bar() + facet_wrap(. ~ numbers)

ggplotly(p)

EDIT 1

This edit is made to suit the needs of the comment. The changes you requested cannot be made directly from ggplot2 so you need to use plotly. There may be a more elegant way to do the chart than my for loops but they seem to work:

library(data.table)
library(ggplot2)
library(plotly)
# make data.table
df <- data.table(
  numbers = rep(1:3, 30),
  letter = sample(c("A", "B", "C", "D"), 90, replace = TRUE),
  status = sample(c("good", "bad", "ugly"), 90, replace = TRUE)
)


# keep unique status values for bars and numbers for facets
traces <- df[,unique(status)]
facets <- df[,unique(numbers)]
# cast df
casted_df <- dcast(df,letter + numbers ~ status )
# initialise list to keep charts   
facetplots <- list()
for(i in 1:length(facets)){
  # initialise chart
  facetplots[[i]] <- plot_ly(type = "bar")
  facet_df <- casted_df[numbers == facets[i]]
  for(j in traces){
    if(i == 1){
      facetplots[[i]] <- add_trace(facetplots[[i]], x = facet_df[,letter], y = facet_df[,get(j)],legendgroup = j , color = j, name = j )

    }else{
      facetplots[[i]] <- add_trace(facetplots[[i]], x = facet_df[,letter], y = facet_df[,get(j)],legendgroup = j, color = j , name = j ,  showlegend = F)

    }
  }
  facetplots[[i]] <- layout(  facetplots[[i]], barmode = "stack")
}

q <- subplot(facetplots, shareX = TRUE)

q

Upvotes: 0

Jonni
Jonni

Reputation: 922

Maybe this is what you're after in ggplot? I couldn't tell if you wanted a ggplots solution or rCharts solution. So this is ggplot.

Add position = "dodge" to your geom_bar argument will mimic the other graph you linked to

ggplot(df, aes(letter, fill = status)) +
 geom_bar(position = "dodge") +
 facet_wrap(.~numbers)

Alternatively, you could "unselect" status, and fill by number -- note, had to make this a factor in this example:

ggplot(df, aes(letter, fill = as.factor(numbers))) +
 geom_bar(position = "dodge") +
 facet_wrap(.~numbers)

Or omit and keep grayscale

ggplot(df, aes(letter)) +
 geom_bar(position = "dodge") +
 facet_wrap(.~numbers)

Upvotes: 0

Related Questions