1

I am learning how to use D3.js and I am trying to render multiple pie charts from JSON data that I fetched from an external API. The data that I am working with look like below

tickers = [{
    "symbol": "GME",
    "buy": 0,
    "hold": 3,
    "period": "2021-08-01",
    "sell": 5,
    "strongBuy": 0,
    "strongSell": 2
}, {
    "symbol": "AMD",
    "buy": 21,
    "hold": 16,
    "period": "2021-08-01",
    "sell": 1,
    "strongBuy": 8,
    "strongSell": 0
}]

I am trying to render a pie chart for each object in the array, but I cant seem to get the data flow correctly to my pie charts. I only want "Strong Sell", "Sell", "Hold", "Buy", and "Strong Buy" information on each pie chart.

I have tried the below codes, and attached screenshots showing the HTML and the pie charts

    var margin = 20, width = 250, height = 250
    var radius = Math.min(width, height) / 2 - margin

    var new_data = tickers.map(function(d){
        if (d){
            var temp = {"Strong Sell": d.strongSell, "Sell": d.sell, "Hold": d.hold, "Buy": d.buy, "Strong Buy": d.strongBuy}
        } else {
            var temp = {"Strong Sell": 0, "Sell": 0, "Hold": 0, "Buy": 0, "Strong Buy": 0}
        }
        return temp
    })

    var color = d3.scaleOrdinal()
        .domain(["Strong Sell", "Sell", "Hold", "Buy", "Strong Buy"])
        .range(["#570e00", "#ff2a00", "#ffff00", "#00ff08", "#00570c"])

    var pie = d3.pie()
        .value(function(d) {return d.value; })

    var data_ready = pie(d3.entries(new_data))

    var recommendSvg = d3.selectAll(".company-recommend")
        .append("svg")
            .attr("width", width)
            .attr("height", height)
        .append("g")
            .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

    recommendSvg
        .selectAll('g')
        .data(data_ready)
        .enter()
        .append('path')
            .attr('d', d3.arc()
                .innerRadius(0)
                .outerRadius(radius)
            )
            .attr('fill', function(d){ return(color(d.data.key)) })
            .attr("stroke", "black")
            .style("stroke-width", "2px")
            .style("opacity", 0.7)

Any help or advice would be greatly appreciated!

Locations where I want pie charts to show

HTML in the console

1 Answer 1

1

Here's a complete example, which assumes that the "company-recommend" divs are already created.

I've modified your code so that you don't need to use d3.entries. I put the data in that format from the start. In addition, I've updated recommendSvg so that the data array is bound to it. This means that each div is bound to one element in the data array. When drawing the pie chart in each group, we then pass the data for that chart to the pie generator and create one path for each slice.

<html>
    <head>
        <script src="https://d3js.org/d3.v7.min.js"></script>
    </head>
    
    <body>
        <div class="company-container">
            <div class="company-profile"></div>
            <div class="company-recommend"></div>
        </div>

        <div class="company-container">
            <div class="company-profile"></div>
            <div class="company-recommend"></div>
        </div>

        <script>
            const tickers = [
                {
                    "symbol": "GME",
                    "buy": 0,
                    "hold": 3,
                    "period": "2021-08-01",
                    "sell": 5,
                    "strongBuy": 0,
                    "strongSell": 2
                },
                {
                    "symbol": "AMD",
                    "buy": 21,
                    "hold": 16,
                    "period": "2021-08-01",
                    "sell": 1,
                    "strongBuy": 8,
                    "strongSell": 0
                }
            ];

            const margin = 20;
            const width = 250;
            const height = 250;
            const radius = Math.min(width, height) / 2 - margin;

            const data = tickers.map(d => [
                { key: 'Strong Sell', value: d.strongSell },
                { key: 'Sell', value: d.sell },
                { key: 'Hold', value: d.hold },
                { key: 'Buy', value: d.buy },
                { key: 'Strong Buy', value: d.strongBuy },
            ]);

            const color = d3.scaleOrdinal()
                .domain(["Strong Sell", "Sell", "Hold", "Buy", "Strong Buy"])
                .range(["#570e00", "#ff2a00", "#ffff00", "#00ff08", "#00570c"]);

            const pie = d3.pie().value(d => d.value);

            const arc = d3.arc()
                .innerRadius(0)
                .outerRadius(radius);

            // bind our data to the divs. add a group to each div.
            const recommendSvg = d3.selectAll('.company-recommend')
                .data(data)
                .append('svg')
                    .attr('width', width)
                    .attr('height', height)
                .append('g')
                    .attr('transform', `translate(${width / 2},${height / 2})`);

            // draw the pie chart in each group
            // by creating one path for each slice
            recommendSvg.selectAll('path')
                .data(d => pie(d))
                .join('path')
                    .attr('d', arc)
                    .attr('fill', d => color(d.data.key))
                    .attr('stroke', 'black')
                    .attr('stroke-width', '2px')
                    .attr('opacity', 0.7);
        </script>
    </body>
</html>
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you so much for the response, that works out perfectly. I will have to read more on how to bind the data like you did there. Once again thanks!
Hi Dan, I am stuck on another problem to display some D3 line graph, would you be kindly take a look at my new question below and offer me your expertise on D3? stackoverflow.com/questions/68779019/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.