'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