'How can I add in Data Labels to my D3 bar chart?
I am completely new at D3. I have managed to create a basic bar chart but I am having trouble adding the data labels.. I tried adding in some things that I researched but it seems to take away the bar chart when I do this.. I still see the bars but not the drawing. Can some please assist on where I would start the svg.selectall(text)?
var data = [
{ ScrumTeamName: 'Name1', score: 4},
{ ScrumTeamName: 'Name2', score: 6},
{ ScrumTeamName: 'Name3', score: 0},
];
var width = 800;
var height = 400;
var margin = { top: 50, bottom: 50, left: 50, right: 50 };
var svg = d3.select("#d3-container")
.append('svg')
.attr('height', height - margin.top - margin.bottom)
.attr('width', width - margin.left - margin.right)
.attr('viewBox', [0, 0, width, height]);
var x = d3.scaleBand()
.domain(d3.range(data.length))
.range([margin.left, width - margin.right])
.padding(0.1);
var y = d3.scaleLinear()
.domain([0, 20])
.range([height - margin.bottom, margin.top]);
svg
.append('g')
.attr('fill', 'royalblue')
.selectAll('rect')
.data(data.sort((a, b) => d3.descending(a.score, b.score)))
.join('rect')
.attr('x', (d, i) => x(i))
.attr('y', (d) => y(d.score))
.attr('height', d => y(0) - y(d.score))
.attr('width', x.bandwidth())
.attr('class', 'rectangle')
function xAxis (g){
g.attr('transform', `translate(0, ${height - margin.bottom})`)
g.call(d3.axisBottom(x).tickFormat(i => data[i].ScrumTeamName))
.attr('font-size', '20px')
}
function yAxis (g){
g.attr('transform', `translate(${margin.left}, 0)`)
.call(d3.axisLeft(y).ticks(null, data.format))
.attr('font-size', '20px')
}
svg.append('g').call(yAxis);
svg.append('g').call(xAxis);
svg.node();
Solution 1:[1]
Here's how I do a simple bar chart label. You can just add this section:
svg.append('g')
.attr('fill', 'royalblue')
.selectAll('text')
.data(data.sort((a, b) => d3.descending(a.score, b.score)))
.join('text')
.text((d) => d.score)
.attr('x', (d, i) => x(i) - x.bandwidth()/2) // center of the bar
.attr('y', (d) => y(d.score) - 2) //lift off the bar
.style('text-anchor','middle')
Solution 2:[2]
I would propose to use regex and its magic to strip away the special characters:
import re
foo = "I'm a dirty string...$@@1##@*((#*@"
clean_foo = re.sub('\W+','', foo )
print(clean_foo) # Does not remove spaces (Outputs Imadirtystring1)
clean_foo2 = re.sub('[^A-Za-z0-9 ]+', '', foo)
print(clean_foo2) # Remove special chars only :D (Outputs IIm a dirty string1)
Solution 3:[3]
You keep on replacing the punctuation once, and then replace again on the original instead of the modified string.
Try this:
def remove_punctuation(string):
punctuation = [",", "."]
for punc in punctuation:
string = string.replace(punc, "")
return string
print(remove_punctuation(string))
Solution 4:[4]
You can use import punctuations which is a list with all punctuations. Then add each character in the sentence to raw_string if it isn't in punctuation.
from string import punctuation
sentence = "the Zen of Python, by Tim Peters. beautiful is better than ugly. explicit is better than implicit. simple is better than complex."
def remove_punctuation(string):
raw_string = ""
for char in string:
if char not in punctuation:
raw_string += char
return raw_string
print(remove_punctuation(sentence))
Solution 5:[5]
If you wish to have the shortest and fastest answer, you can just remove everything with a translation table like so:
>>> import string
>>> s = "the Zen of Python, by Tim Peters. beautiful is better than ugly. explicit is better than implicit. simple is better than complex."
>>> s.translate(str.maketrans("", "", string.punctuation))
'the Zen of Python by Tim Peters beautiful is better than ugly explicit is better than implicit simple is better than complex'
Solution 6:[6]
In your code you have 2 loops, the inner loop replaces first the comma using string, and for the dot it is using the same unmodified value of string again.
So the string is 2 times used as the source, and the replacement of the second iteration replacing the dot is only stored in raw_string giving you the result with only the dots removed.
You might use a single call using a character class matching either . or , with re.sub
import re
string = "the Zen of Python, by Tim Peters. beautiful is better than ugly. explicit is better than implicit. simple is better than complex."
def remove_punctuation(string):
return re.sub(r"[,.]", "", string)
print(remove_punctuation(string))
Output
the Zen of Python by Tim Peters beautiful is better than ugly explicit is better than implicit simple is better than complex
Solution 7:[7]
You redefine raw_string at every iteration from scratch, so you only see the effect of the last iteration. You need to 'accumulate' the modifications:
def remove_punctuation(string):
raw_string = string
punctuation = [",", "."]
for char in string:
if char in punctuation:
raw_string = raw_string.replace(char, "")
return raw_string
You can also do this using 'list' comprehension:
"".join(c for c in string if c not in punctuation)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | SmokeyShakers |
| Solution 2 | Allan Chua |
| Solution 3 | Bharel |
| Solution 4 | Old_Arrack |
| Solution 5 | Bharel |
| Solution 6 | |
| Solution 7 |
