D3.js d3饼图的分组数据
这里有个d3新手。我正在尝试将csv文件中的所有元素分组,以便在饼图上显示为单个序列D3.js d3饼图的分组数据,d3.js,D3.js,这里有个d3新手。我正在尝试将csv文件中的所有元素分组,以便在饼图上显示为单个序列 <script> var width = 960, height = 500, radius = Math.min(width, height) / 2; var color = d3.scale.ordinal() .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8
<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>
这是csv文件。(一个更大文件的简化版本,其中我将20-30个条目分组):
这就是我现在得到的:
我希望将红色元素和相应的计数分组,使其显示如下:
可能有一个简单的解决方案。这是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>
可变宽度=960,
高度=500,
半径=数学最小值(宽度、高度)/2;
var color=d3.scale.ordinal()
.范围([“98abc5”、“8a89a6”、“7b6888”、“6b486b”、“a05d56”、“d0743c”、“ff8c00”);
var arc=d3.svg.arc()
.外层(半径-10)
.内半径(半径-70);
var pie=d3.layout.pie()
.sort(空)
.value(函数(d){返回d.count;});
var svg=d3.选择(“正文”).追加(“svg”)
.attr(“宽度”,宽度)
.attr(“高度”,高度)
.附加(“g”)
.attr(“变换”、“平移”(+width/2+)、“+height/2+”);
d3.csv(“data.csv”,函数(错误,数据){
var g=svg.selectAll(“.arc”)
.数据(pie(数据))
.enter().append(“g”)
.attr(“类”、“弧”);
g、 附加(“路径”)
.attr(“d”,弧)
.style(“fill”,函数(d){返回颜色(d.data.colors);});
g、 附加(“文本”)
.attr(“变换”,函数(d){return“translate”(+arc.centroid(d)+”);})
.attr(“dy”,“.35em”)
.style(“文本锚定”、“中间”)
.text(函数(d){返回d.data.colors;});
})
当我必须为d3执行数据转换任务时,我更喜欢在后端执行,因为您可以模拟数据并对转换引擎运行测试。然后你只是把数据发送到d3。也就是说:
(C#MVC Web Api示例)
public class RestaurantViewModel
{
公共列表餐厅数据{get;set;}
}
公共类餐厅数据系列
{
公共字符串Zipcode{get;set;}
公共列表数据系列{get;set;}
}
公共类ScoreDataPoint
{
公共字符串分数{get;set;}
公共整数计数{get;set;}
}
公共餐厅可视模型GetRestaurantSeries()
{
var csvConfiguration=新的csvConfiguration();
csvConfiguration.RegisterClassMap();
const string fileName=“餐厅检查得分图表.csv”;
使用(var streamReader=_fileSource.GetFile(文件名))
{
var csvReader=新csvReader(streamReader,CSV配置);
var restaurantDataPoints=csvReader.GetRecords().ToList();
可变Zipcode=
restaurantDataPoints.DistinctBy(point=>point.Zipcode).Select(point=>point.Zipcode.ToList();//不同的zips
var restaurantDataSeries=新列表();
var scoreList=新列表{“A”、“B”、“C”、“D”};
foreach(zipcodes中的var zipcode)
{
var currentRestaurantDataSeries=新RestaurantDataSeries
{
Zipcode=Zipcode,
DataSeries=新列表()
};
foreach(分数表中的var分数)
{
currentRestaurantDataSeries.DataSeries.Add(新的ScoreDataPoint
{
分数=分数,
计数=
餐厅数据点。计数(
point=>point.Zipcode==Zipcode&&ScoreConverter.GetScore(point.Score)==Score)
});
}
添加(currentRestaurantDataSeries);
}
返回新RestaurantViewModel{RestaurantData=RestaurantData Series};
}
}
然后我使用D3中的格式化列表,非常简单,无需使用javascript进行数据转换。但是,我发现在静态类型语言中使用数据要简单得多,我可以在编译时而不是运行时对名称和转换进行验证。如果您想要一个直接的
d3
解决方案,那么:
完整的例子
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.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);
...