1

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?

OTStats
  • 1,820
  • 1
  • 13
  • 22
maleta
  • 383
  • 1
  • 2
  • 10

2 Answers2

0

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)
Jonni
  • 804
  • 5
  • 16
  • Sorry, I meant I want an rCharts solution because I would like it to be interactive. I edited my post to make it more clear. – maleta Jun 24 '19 at 21:05
0

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
Jon Nagra
  • 1,538
  • 1
  • 16
  • 36
  • 1
    I was just hoping for a functionality where I could select and deselect "good", "bad", and "ugly", and the bars would automatically adjust themselves. I can show and hide the different categories--but the bars themselves do not change (so if I deselect the category in the middle of the bars, the top of the bars remain hovering over it rather than the bars morphing). – maleta Jun 25 '19 at 18:52