如何从具有多个对象的单个数组使用 D3 创建多个饼图?

How to create multiple pie charts with D3 from a single array with multiple objects?

我正在学习如何使用 D3.js,我正在尝试根据从外部 API 获取的 JSON 数据呈现多个饼图。我正在处理的数据如下所示

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
}]

我正在尝试为数组中的每个对象呈现一个饼图,但我似乎无法使数据流正确地流向我的饼图。我只想要每个饼图上的“强力卖出”、“卖出”、“持有”、“买入”和“强力买入”信息。

我已经尝试了以下代码,并附上了显示 HTML 和饼图

的屏幕截图
    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)

如有任何帮助或建议,我们将不胜感激!

Locations where I want pie charts to show

HTML in the console

这是一个完整的示例,假设“公司推荐”div已经创建。

我已经修改了您的代码,因此您不需要使用 d3.entries。我从一开始就把数据放在那种格式中。此外,我更新了 recommendSvg 以便 data 数组绑定到它。这意味着每个 div 都绑定到 data 数组中的一个元素。在每组中绘制饼图时,我们将该图表的数据传递给 pie 生成器并为每个切片创建一个路径。

<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>