为d3饼图分组数据

时间:2015-05-17 15:15:28

标签: d3.js

这里有一个d3新手。我正在尝试将csv文件中的所有元素分组,以便在饼图上显示为单个segemnt。

这是csv文件。 (一个更大的文件的简化版本,我将20-30个条目分组):

colors,count
red,34
blue,33
green,21
yellow,41
red,16
red, 21
orange,51

这就是我现在所得到的: http://bricbracs.com/test/

我想要将红色元素和相应的计数分组,以便它看起来像这样: http://bricbracs.com/test1/

可能有一个简单的解决方案。这是d3脚本。没什么好看的,只是你是标准的饼图。

<script>
var width = 960,
    height = 500,
    radius = Math.min(width, height) / 2;

var color = d3.scale.ordinal()
    .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);

var arc = d3.svg.arc()
    .outerRadius(radius - 10)
    .innerRadius(radius - 70);

var pie = d3.layout.pie()
    .sort(null)
    .value(function(d) { return d.count; });

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
  .append("g")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

d3.csv("data.csv", function(error, data) {

  var g = svg.selectAll(".arc")
      .data(pie(data))
      .enter().append("g")
      .attr("class", "arc");

  g.append("path")
      .attr("d", arc)
      .style("fill", function(d) { return color(d.data.colors); });

  g.append("text")
      .attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; })
      .attr("dy", ".35em")
      .style("text-anchor", "middle")
      .text(function(d) { return d.data.colors; });
})
</script>

2 个答案:

答案 0 :(得分:1)

有很多方法可以做到这一点。如果您想要一个直接d3解决方案,那么d3.nest

怎么样?
d3.csv("data.csv", function(error, data) {
  var data = d3.nest()
    .key(function(d) {
      return d.colors;
    })
    .rollup(function(d) {
      return d3.sum(d, function(g) {
        return g.count;
      });
    }).entries(data);

...

完整示例here

答案 1 :(得分:0)

当我必须为d3执行数据转换任务时,我更喜欢在后端执行此操作,因为您可以模拟数据并针对转换引擎运行测试。然后你只是将数据发送到d3。即:

(C#MVC Web Api示例)

public class RestaurantViewModel
{
    public List<RestaurantDataSeries> RestaurantData { get; set; }
}
public class RestaurantDataSeries
{
    public string Zipcode { get; set; }
    public List<ScoreDataPoint> DataSeries { get; set; }
}

public class ScoreDataPoint
{
    public string Score { get; set; }
    public int Count { get; set; }
}

public RestaurantViewModel GetRestaurantSeries()
{
    var csvConfiguration = new CsvConfiguration();
    csvConfiguration.RegisterClassMap<RestaurantDataMap>();
    const string fileName = "Restaurant_Inspection_Scores_Chart.csv";
    using (var streamReader = _fileSource.GetFile(fileName))
    {
        var csvReader = new CsvReader(streamReader, csvConfiguration);
        var restaurantDataPoints = csvReader.GetRecords<RestaurantData>().ToList();
        var zipcodes =
            restaurantDataPoints.DistinctBy(point => point.Zipcode).Select(point => point.Zipcode).ToList(); //Distinct zips

        var restaurantDataSeries = new List<RestaurantDataSeries>();
        var scoreList = new List<string> {"A", "B", "C", "D"};
        foreach (var zipcode in zipcodes)
        {
            var currentRestaurantDataSeries = new RestaurantDataSeries
            {
                Zipcode = zipcode,
                DataSeries = new List<ScoreDataPoint>()
            };

            foreach (var score in scoreList)
            {

                currentRestaurantDataSeries.DataSeries.Add(new ScoreDataPoint
                {
                    Score = score,
                    Count =
                        restaurantDataPoints.Count(
                            point => point.Zipcode == zipcode && ScoreConverter.GetScore(point.Score) == score)
                });
            }
            restaurantDataSeries.Add(currentRestaurantDataSeries);
        }

        return new RestaurantViewModel {RestaurantData = restaurantDataSeries};
    }
}

然后我在D3中使用格式化的列表,所有这些都很简单,而无需在javascript中进行数据转换。但话说回来,我发现在静态类型语言中使用数据很多更简单,我可以在编译时而不是运行时对名称和转换进行验证。