{"action":"opened","issue":{"url":"https://api.github.com/repos/bokeh/bokeh/issues/1780","labels_url":"https://api.github.com/repos/bokeh/bokeh/issues/1780/labels{/name}","comments_url":"https://api.github.com/repos/bokeh/bokeh/issues/1780/comments","events_url":"https://api.github.com/repos/bokeh/bokeh/issues/1780/events","html_url":"https://github.com/bokeh/bokeh/issues/1780","id":55834221,"number":1780,"title":"Negative bar charts","user":{"login":"birdsarah","id":1796208,"avatar_url":"https://avatars.githubusercontent.com/u/1796208?v=3","gravatar_id":"","url":"https://api.github.com/users/birdsarah","html_url":"https://github.com/birdsarah","followers_url":"https://api.github.com/users/birdsarah/followers","following_url":"https://api.github.com/users/birdsarah/following{/other_user}","gists_url":"https://api.github.com/users/birdsarah/gists{/gist_id}","starred_url":"https://api.github.com/users/birdsarah/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/birdsarah/subscriptions","organizations_url":"https://api.github.com/users/birdsarah/orgs","repos_url":"https://api.github.com/users/birdsarah/repos","events_url":"https://api.github.com/users/birdsarah/events{/privacy}","received_events_url":"https://api.github.com/users/birdsarah/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2015-01-28T23:44:57Z","updated_at":"2015-01-28T23:44:57Z","closed_at":null,"body":"Hi, \r\n\r\nI'm not sure if you've considered this already, and decided not to do it. I'm happy to do a pull request, but wanted to check in to make sure this was something that was desired, and what the direction would be.\r\n\r\nI had a dataframe of negative data, and bokeh.charts.Bar did not do the right thing when automatically setting the ydr.\r\n\r\nThe quick solution to my needs was:\r\n````python\r\nclass NegativeBar(Bar):\r\n    def get_source(self):                                                                                                                           \r\n        \"\"\"Push the Bar data into the ColumnDataSource and calculate                                                                                \r\n        the proper ranges.                                                                                                                          \r\n        \"\"\"                                                                                                                                         \r\n        self.source = ColumnDataSource(self.data)                                                                                                   \r\n        self.xdr = FactorRange(factors=self.source.data[\"cat\"])                                                                                     \r\n                                                                                                                                                    \r\n        if self._stacked:                                                                                                                           \r\n            self.ydr = Range1d(start=0, end=1.1 * min(self.data['zero']))                                                                           \r\n        else:                                                                                                                                       \r\n            cat = [i for i in self.attr                                                                                                             \r\n                   if not i.startswith((\"mid\", \"stacked\", \"cat\"))]                                                                                  \r\n            end = 1.1 * min(min(self.data[i]) for i in cat)                                                                                         \r\n            self.ydr = Range1d(start=0, end=end)  \r\n````\r\nNote the `min`s instead of `max`s.\r\n\r\n(This doesn't worked for positive & negative data as the start is set at 0, not the min/max depending on which way you're coming from).\r\n\r\nI think the out of the box behavior is good. It does something sensible and nothing too fancy. Trying to guess good start and end for all the possible data is clearly not a good route.\r\n\r\nFor me though, the ability for a cleaner override would be great: `get_xdr` and `get_ydr` methods that I can override, or optionally set on `__init__` which seems to be bokeh's preferred way of doing things."}}