score:2

Accepted answer

You have two problems, the first one being a simple selection order and the second one being conceptual.

The first problem is this: when you write

 var bar = chart.selectAll("g")

for creating your groups, you're selecting groups that already exist in your SVG, which are the axes and an initial group added to the SVG.

So, select something else, something that doesn't exist:

var bar = chart.selectAll(".foo")

Your second problem is conceptual: although you're correct about being impossible to append a text to a rect, you don't need g elements to achieve what you want. Just create a rect selection and a text selection, and append both to the SVG.

But if you want to add the groups, this is what you have to do.

First, in the data binding, select something that doesn't exist:

var groups = chart.selectAll(".groups")
    .data(data)
    .enter()
    .append("g")
    .attr("transform", function(d) {
        return "translate(" + x(d.letter) + ",0)";
    });

Translate only the x position of the groups, the y position of their elements will be set individually.

Then, create the bars:

var bar = groups.append("rect")
    .attr("y", function(d) {
        return y(d.value);
    })
    .attr("width", x.bandwidth())
    .attr("height", function(d) {
        return height - y(d.value);
    });

And finally your texts:

var text = groups.append("text")
    .attr("y", function(d) {
        return y(d.value) - 6;
    })
    .attr("x", x.bandwidth() / 2)
    .attr("text-anchor", "middle")
    .text(function(d) {
        return d.value
    });

This is a demo using your code and fake data:

var data = d3.csvParse(d3.select("#csv").text());

data.forEach(function(d) {
    d.value = +d.value
});

var margin = {
        top: 20,
        right: 30,
        bottom: 30,
        left: 40
    },
    width = 960,
    height = 500;

var x = d3.scaleBand()
    .rangeRound([0, width])
    .padding(0.3);

var y = d3.scaleLinear()
    .range([height, 0]);

var xAxis = d3.axisBottom(x),
    yAxis = d3.axisLeft(y)
    .ticks(10, "%").tickPadding(11);

var chart = d3.select(".chart")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

x.domain(data.map(function(d) {
    return d.letter;
}));
//set domain of scale, it is now known
y.domain([0, d3.max(data, function(d) {
    return d.value;
})]);

var groups = chart.selectAll(".groups")
    .data(data)
    .enter()
    .append("g")
    .attr("transform", function(d) {
        return "translate(" + x(d.letter) + ",0)";
    })

var bar = groups.append("rect").attr("y", function(d) {
        return y(d.value);
    })
    .attr("width", x.bandwidth())
    .attr("height", function(d) {
        return height - y(d.value);
    });

var text = groups.append("text")
    .attr("y", function(d) {
        return y(d.value) - 6;
    })
    .attr("x", x.bandwidth() / 2)
    .attr("text-anchor", "middle")
    .text(function(d) {
        return d.value
    });

//append the xAis
chart.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + (height) + ")")
    .call(xAxis);

chart.append("g")
    .attr("class", "y axis")
    .call(yAxis)
    .append("text")
    .attr("transform", "rotate(-90)")
    .attr("y", 6)
    .attr("dy", ".71em")
    .style("text-anchor", "end")
    .text("Frequency");
pre {
	display: none;
}

rect {
	fill: teal;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg class="chart"></svg>
<pre id="csv">letter,value
A,.08167
B,.01492
C,.02782
D,.04253
E,.12702
F,.02288
G,.02015</pre>


Related Query

More Query from same tag