5

I've searched, so please forgive me if I'm missing something.

Let's assume a dataframe that contains Name, Date, Calories, where Calories is the total number of calories that person consumed that day.

Name    Date    Calories
Amy     1/1/01  1500
Amy     1/2/01  1600
Amy     ...     ...
Sue     1/1/01  1450
Sue     1/1/02  1500
Sue     ...     ...
Jim     ...     ...

What I'd like to do is to use ggvis to plot calories for each person (Name). I know I can use dplyr's group_by, and get this on a single plot, but that will be too busy. And I know I could use dplyr's filter and filter out each person and make a graph for each person, but that doesn't scale.

Is there a way to have ggvis spit out a plot of calories per day for each person automatically?

Note that I tried creating a function like the below:

makeCharts <- function(myName){
   myTbl %>% filter(Name == myName) %>% ggvis(~Date, ~Calories)
}

It works great when you call it manually:

makeCharts("Amy")

But when you call it via sapply:

sapply(levels(myTbl$Name), makeCharts)

The output looks like this:

           Amy    Sue    Jim    John   Sally  Frank  Sandy   etc...     
marks      List,0 List,0 List,0 List,0 List,0 List,0 List,0 List,0 List,0  List,0 List,0 List,0 List,0  List,0 List,0
data       List,1 List,1 List,1 List,1 List,1 List,1 List,1 List,1 List,1  List,1 List,1 List,1 List,1  List,1 List,1
props      List,1 List,1 List,1 List,1 List,1 List,1 List,1 List,1 List,1  List,1 List,1 List,1 List,1  List,1 List,1
reactives  List,0 List,0 List,0 List,0 List,0 List,0 List,0 List,0 List,0  List,0 List,0 List,0 List,0  List,0 List,0
scales     List,0 List,0 List,0 List,0 List,0 List,0 List,0 List,0 List,0  List,0 List,0 List,0 List,0  List,0 List,0
axes       List,0 List,0 List,0 List,0 List,0 List,0 List,0 List,0 List,0  List,0 List,0 List,0 List,0  List,0 List,0
legends    List,0 List,0 List,0 List,0 List,0 List,0 List,0 List,0 List,0  List,0 List,0 List,0 List,0  List,0 List,0
controls   List,0 List,0 List,0 List,0 List,0 List,0 List,0 List,0 List,0  List,0 List,0 List,0 List,0  List,0 List,0
connectors List,0 List,0 List,0 List,0 List,0 List,0 List,0 List,0 List,0  List,0 List,0 List,0 List,0  List,0 List,0
handlers   List,0 List,0 List,0 List,0 List,0 List,0 List,0 List,0 List,0  List,0 List,0 List,0 List,0  List,0 List,0
options    List,0 List,0 List,0 List,0 List,0 List,0 List,0 List,0 List,0  List,0 List,0 List,0 List,0  List,0 List,0
cur_data   ?      ?      ?      ?      ?      ?      ?      ?      ?       ?      ?      ?      ?       ?      ?     
cur_props  List,2 List,2 List,2 List,2 List,2 List,2 List,2 List,2 List,2  List,2 List,2 List,2 List,2  List,2 List,2
cur_vis    NULL   NULL   NULL   NULL   NULL   NULL   NULL   NULL   NULL    NULL   NULL   NULL   NULL    NULL   NULL  
John Tarr
  • 717
  • 1
  • 9
  • 21
  • I'm not very familiar with ggvis, but only with ggplot2, which has facet_* functions that - if I understand correctly - do what you want (http://www.cookbook-r.com/Graphs/Facets_%28ggplot2%29/). This exact capability seems not yet to be implemented in ggvis according to the Jim Hester's ggplot2-to-ggvis page (http://www.jimhester.com/ggplot2ToGgvis/)... There might be another solution though. – maj Aug 17 '15 at 20:31
  • Yes, I saw that ggplot had facets, which seemed right, and I also saw Hadley post that it was coming to ggvis, but I don't think it is there yet. I am really hoping to learn how to do this with ggvis, as I'm new to R, and want to really learn a few packages well before moving on (dplyr and ggvis). I believe R is robust enough to allow me to do this somehow. – John Tarr Aug 17 '15 at 20:34

1 Answers1

5

One option is to use do. The do function from dplyr can be used for functions that return objects like this, and allows you to easily make a separate plot for each level of some grouping variable.

For your basic example, you just need to edit your function with the desired plot but with the dataset as the only argument.

makeCharts = function(dat) {
    dat %>% ggvis(~Date, ~Calories)
}

Then group your dataset and make a plot per group via do. The . refers to the dataset for each group. I named the output column that contains the list of plots plots.

allplots = myTbl %>%
    group_by(Name) %>%
    do(plots = makeCharts(.))

The resulting object looks like this:

Source: local data frame [2 x 2]
Groups: <by row>

  Name      plots
1  Amy <S3:ggvis>
2  Sue <S3:ggvis>

To print all the plots to the plotting window in a row, you just need to run allplots$plots. You can extract just a single plot via, e.g., allplots$plots[[1]].

Edit

You can use anything from the dataset within do by referring to the dataset via .. For example, if you wanted to add a title with the group name like this answer shows how to do, you could make a new function to include this with a second argument:

makeCharts2 = function(dat, group) {
    dat %>% ggvis(~Date, ~Calories) %>%
            add_axis("x", title = "Date") %>%
            add_axis("x", orient = "top", ticks = 0, title = paste("Plot for", group),
                         properties = axis_props(
                                axis = list(stroke = "white"),
                                labels = list(fontSize = 0)))
}

Then just add the group name as the second argument to the function. One way to do this is via unique.

allplots2 = myTbl %>%
    group_by(Name) %>%
    do(plots = makeCharts2(., unique(.$Name)))
Community
  • 1
  • 1
aosmith
  • 34,856
  • 9
  • 84
  • 118
  • This worked perfect, despite the R sacrilege of using = for assignment. =) – John Tarr Aug 18 '15 at 01:21
  • Ok, this worked, but how do I access the unique names? I can create the allplots variable, and print it just like you said, but I want to put a title on each chart. Not seeing how to access the name to list it as a header for each chart? – John Tarr Aug 18 '15 at 01:58