score:57

*Accepted answer*

OK, let's say you have an array of numbers as your dataset, and this includes some positive and negative values:

```
var data = [-15, -20, -22, -18, 2, 6, -26, -18];
```

You'll want two scales to construct a bar chart. You need one quantitative scale (typically a linear scale) to compute the bar positions along the *x*-axis, and a second ordinal scale to compute the bar positions along the *y*-axis.

For the quantitative scale, you typically need to compute the domain of your data, which is based on the minimum and maximum value. An easy way to do that is via d3.extent:

```
var x = d3.scale.linear()
.domain(d3.extent(data))
.range([0, width]);
```

You might also want to nice the scale to round the extent slightly. As another example, sometimes you want the zero-value to be centered in the middle of the canvas, in which case you'll want to take the greater of the minimum and maximum value:

```
var x0 = Math.max(-d3.min(data), d3.max(data));
var x = d3.scale.linear()
.domain([-x0, x0])
.range([0, width])
.nice();
```

Alternatively, you can hard-code whatever domain you want.

```
var x = d3.scale.linear()
.domain([-30, 30])
.range([0, width]);
```

For the *y*-axis, you'll want to use rangeRoundBands to divide the vertical space into bands for each bar. This also lets you specify the amount of padding between bars. Often an ordinal scale is used with some identifying dataâ€”such as a name or a unique id. However, you can also use ordinal scales in conjunction with the data's index:

```
var y = d3.scale.ordinal()
.domain(d3.range(data.length))
.rangeRoundBands([0, height], .2);
```

Now that you've got your two scales, you can create the rect elements to display the bars. The one tricky part is that in SVG, rects are positioned (the `x`

and `y`

attributes) based on their top-left corner. So we need to use the *x*- and *y*-scales to compute the position of the top-left corner, and that depends on whether the associated value is positive or negative: if the value is positive, then the data value determines the right edge of the bar, while if it's negative, it determines the left edge of the bar. Hence the conditionals here:

```
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d, i) { return x(Math.min(0, d)); })
.attr("y", function(d, i) { return y(i); })
.attr("width", function(d, i) { return Math.abs(x(d) - x(0)); })
.attr("height", y.rangeBand());
```

Lastly, you can add an axis to display tick marks on top. You might also compute a fill style (or even a gradient) to alter the differentiate the appearance of positive and negative values. Putting it all together:

Source: stackoverflow.com

#### Related Query

- Bar chart with negative values
- d3.js stacked bar chart with positive and negative values
- d3.js v4 bar chart with negative values on y axis
- Transitioning a bar chart with negative values for the width
- D3 bar chart not working properly with all negative and positive values
- D3 v4 bar chart X axis with negative values
- d3,js setting X and Y domains on Horizontal Bar Chart with all negative values
- Special donut chart with different rings/arcs for positive and negative values
- Build D3js Area Chart with negative values
- d3.js Bar chart supporting negative values
- Unable to handle negative values on d3 bar chart
- d3.js bar which starts with negative values
- d3 redraw bar chart with new values
- Draw Line chart with positive & negative values
- D3.js: Adding a time axis to a bar graph with negative values
- Values are not reflecting Dynamically in D3 Bar Chart using. Overlapping occur with the existing Graph.
- Avoid negative axes values for dc powered d3 bubble chart with crossfilter
- D3.js line chart with negative values
- dc.js row chart with negative values doesn't show full rows
- Negative values not showing in grouped bar chart
- Grouped Bar Chart with negative value d3
- D3 - Chart with positive and negative values
- d3.js horizontal bar graph with positive and negative values - move y axis labels to far left side of graph
- Bar chart to take account of negative values
- Dynamically Update Bar Chart in Javascript With Sliders Values
- Stacked bar chart with negative JSON data
- D3 Bar Chart Negative Values not Showing Up
- nvd3 line chart with string values on x-axis
- How to update d3.js bar chart with new data
- Make simple bar chart using C3 with separate columns on the x axis

#### More Query from same tag

- meteor piechart doesn't show up completely
- How can I successfully load dimple.js when require.js is present?
- How can I add labels inside the points in a scatterplot?
- update data of D3.js treemap
- Building a reusable D3.js chart in Angular with 100% width?
- D3.js Heatmap colors based on variable value instead of value for the whole table
- Staggered? Chained? Single DOM element addressed by a series of d3 transitions of varying delay() and duration()
- D3js v3 to v5 upgrade: unable to convert strings to integers
- javascript/D3 basics: If asynchronous call, why is code outside of json request?
- Zoomable treemap with tooltips at the bottom
- D3 Plot array of circles
- What is the difference between svg's x and dx attribute?
- Selecting DOM elements in Chrome console
- Parsing header row with dates when importing csv data
- How to get out of nested selectAll in D3JS?
- Drag nvd3 line graph using drag behaviour
- D3.js json error when making tree
- To find nearest rect elements within specified radius or distance of another rect element using D3
- Set the entry of a node in force layout
- d3 loop over same item multiple times
- Data bound to children is not updated with new data
- Organization chart - tree, online, dynamic, collapsible, pictures - in D3
- dynamic tooltip for multiline in d3.js
- Draw vertical line after n data points in d3
- How to understand `constant(_), histogram` in `histogram.value` which is part of `d3.histogram` source code?
- d3 zoom behavior. Increasing the scale in small increments
- Using this d3 gauge in django?
- D3.js - Changing force directed graph node from circle to svg:rect
- D3 Force directed layout + All nodes to original positions
- Clicking on node in dagre-d3