Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bar chart API #596

Closed
hamilton opened this issue Jan 19, 2016 · 4 comments
Closed

bar chart API #596

hamilton opened this issue Jan 19, 2016 · 4 comments
Assignees
Labels
Milestone

Comments

@hamilton
Copy link
Collaborator

Work towards the completion of #580. The API is a major component of this.

Here are some of the assumptions we can make for bar charts:

  • most of the time, I imagine we are still loading something in a CSV-but-javascript style, such as an array of objects. In this case, the data is "vertically oriented" - each bar would be a single value from an object in the array, and the label for each graph will be the other value.
  • we should accept and support grouping bars together, and stacking them.
  • we should have a good way to include something along the lines of markers per-bar, as well as some sort of baseline per-bar functionality.
  • we should have a simple way to provide subtitles for some bars. For instance, if I am showing the results from a number of polls from a presidential primary state, it may be useful to allow a subtitle for each bar label that says when the poll was conducted. Providing just a small amount of additional metadata like this is often very useful.
  • all of the existing rollover options should work fairly simply with bar charts.

Regarding the data format, suppose we have

var data = [
    {field1: 10, field2: 'a'},
    {field1: 20, field2: 'b'}
];

And we want to plot field1 from these two objects, while labelling them field2.

So the call to MG.data_graphic for a simple bar chart would look like:

MG.data_graphic({
  data: data,
  chart_type: 'bar',
  x_accessor: 'field1', // this selects the value of the field
  y_accessor: 'field2' // this selects the label
})

What about grouping the bars together, similar in style to ggplot's dodging, or stacking bars? Here, we'll make a more involved data set, involving fruits by type and size, roughly.

The core premise is that we want to dodge by class below, and stack by size.

var data = [
    {quantity: 20, name: 'lime', class: 'citrus', size:'small'},
    {quantity: 20, name: 'lemon', class:'citrus', size:'small'},
    {quantity: 20, name: 'grapefruit', class:'citrus', size:'large'},
    {quantity: 10, name: 'navel', class: 'citrus', , size:'large'},
    {quantity: 20, name: 'nectarine', class:'stone fruit', size:'large'},
    {quantity: 20, name: 'peach', class:'stone fruit', size:'large'},
    {quantity: 20, name: 'plum', class:'stone fruit', size:'small'},
    {quantity: 20, name: 'pluot', class:'stone fruit', size:'small'}

];
MG.data_graphic({
  data: data,
  chart_type: 'bar',
  x_accessor: 'quantity', // this selects the value of the field
  y_accessor: 'name' // this selects the label
 group_accessor: 'class'    // this will group each of these accordingly, putting the bars next to each other
stack_accessor: 'size'      // this will stack by size, so lemon and lime will be stacked on top of each other, for instance
})
@hamilton hamilton added this to the v2.9 milestone Jan 19, 2016
@hamilton
Copy link
Collaborator Author

Also worth noting - at the moment this x_accessor and y_accessor applies to bars that are oriented horizontally, not vertically, for the moment.

hamilton added a commit that referenced this issue Jan 21, 2016
@hamilton hamilton self-assigned this Jan 21, 2016
hamilton added a commit that referenced this issue Jan 26, 2016
@klahnakoski
Copy link

I believe you will need an additional concept of "series", so you may one day put bar charts, line charts, ?and scatter plots?, all on the same area.

{
    "data": data,
    "series": [
        {
        "name": "a", //something interesting
        "type": "bar",   //the chart type should be a property of the series
        "value": "field1",  //vertical height
        "axis": "y"
        }
    ],
    "axis":{ 
        "x":{
            "type": "category",
            "parts": ["b", "a"],  //the order we want to show the bars
            "accessor": "field2"  
        },
        "y":{ // we can just leave this out since it is empty
        }
    }
}

Your fruit example is interesting, I have not used bar charts in two categorical dimensions [class x size] before.

{
    "data": data,
    "series": [
        {
        "type":"stacked", 
        "name": "Category of Fruit",
        "value": ["size", "quantity"],  // 2d accessor
        "axis": ["z", "y"],   //order matters if you are stacking
        "label": "size"   //give the bars some nice names
        }
    ],
    "axis":{
        "x":{
            "type":"category",
            "accessor": "class"
        },
        "z":{ //the stacked "dimension" 
            "type":"category",
            "accessor": "size"
        }
    }
}

Using series allows us to plot bars and lines on areas with a time axis.

var data = [
    {quantity: 19, name: 'lime', class: 'citrus', size:'small', timestamp: 1453973538},
    {quantity: 25, name: 'lemon', class:'citrus', size:'small' , timestamp: 1453852899},
    {quantity: 13, name: 'grapefruit', class:'citrus', size:'large', timestamp: 1453766400},
    {quantity: 6, name: 'navel', class: 'citrus', , size:'large', timestamp: 1453776400},
    {quantity: 11, name: 'nectarine', class:'stone fruit', size:'large', timestamp: 1453826400},
    {quantity: 14, name: 'peach', class:'stone fruit', size:'large', timestamp: 1453852800},
    {quantity: 21, name: 'plum', class:'stone fruit', size:'small', timestamp: 1453892800},
    {quantity: 20, name: 'pluot', class:'stone fruit', size:'small', timestamp: 1453973538}
];

{
    "data": data,
    "series": [
        {//day's fruit purchases, split by type
        "name": "Type of Fruit", 
        "type": "stacked",
        "value": "quantity",
        "axis": "y",  //we could leave this out, and assume it is a default 
        },
        {//identical height bar, but split by size rather than class
        "name": "Size",
        "type": "stacked",
        "value": "quantity"  //vertical height (assume axis: "y")
        }
    ],
    "axis":{
        "x":{
            "type":"time", 
            "accessor": function(d){return floor(d.timestamp)};
        }
    }
}

I am not attached to the specific format or property names. My only objective is to convince you to use a series array to specify the details to chart.

@hamilton
Copy link
Collaborator Author

I'm not against this idea, but my initial reaction would be a considerable addition of complexity and obfuscation that goes against what the library API is designed for. I'd be more interested in seeing the use cases for adding two plot types together, and provide options for those use-cases. My working theory is, for the vast majority of charts, something simple does the trick, with the simple, good-out-of-the-box approach being more of a focus than the customizability. At the very least we're finding that with lines and points.

hamilton added a commit that referenced this issue Jan 28, 2016
…w color_accessor works), and #602 (coloring , implementation of group_accessor, legend work)
@hamilton
Copy link
Collaborator Author

(@klahnakoski I feel your comment should be made in a separate issue, not conflated with this one)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants