Класс SimpleNamespace
может использоваться для создания новых атрибутов с помощью setattr
или подкласса SimpleNamespace
и создания вашей собственной функции для добавления новых имен атрибутов (переменных).
from types import SimpleNamespace
variables = {"b":"B","c":"C"}
a = SimpleNamespace(**v)
setattr(a,"g","G")
a.g = "G+"
something = a.a
В вашем коде было несколько ошибок, поэтому я попытался исправить некоторые из них.
Элементы вашей диаграммы (т.е. столбцы и оси) должны быть добавлены в группу. Это позволит перемещать / переводить соответствующим образом по мере необходимости. Я создаю переменную chart
и назначаю эти элементы ей, а не непосредственно svg. Это упрощает просмотр структуры при просмотре в консоли.
Высота области легенды должна быть объявлена и учтена в таблице. Я объявил это как переменную legendh
и учел это в диапазоне оси Y.
Если вы хотите, чтобы ваша группа легенд появлялась под диаграммой, ее необходимо перевести под диаграмму. В вашем предыдущем преобразовании для упомянутой группы .attr('transform', 'translate(' + (padding + 12) + ',0)');
были заданы координаты y 0. Я изменил его на .attr('transform', 'translate(' + (padding + 12) + ','+ (height - legendh) + ')');
. Это говорит группе легенды двигаться вниз от вершины на величину height - legendh
, таким образом, помещая ее под диаграмму.
Наконец, цвета в легенде не совпадали с цветами в диаграмме / столбцах. Это было потому, что заполнение вашего бара было установлено d.key
, а заполнение легенды было основано на i
. Я решил сделать его равномерным и получить цвет, используя z(i)
.
Вот рабочий блок: https://bl.ocks.org/akulmehta/80153b35ab7498d30408f92cfa50f356
Вот рабочий код: [ 1121]
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>D3 Example</title>
<script src="https://d3js.org/d3.v4.min.js"></script>
<link href='https://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>
<style>
</style>
</head>
<style>
</style>
<body>
<div class="canvas">
</div>
<script>
var data = [
{month: "Q1-2016", apples: 3840, bananas: 1920, cherries: -1960},
{month: "Q2-2016", apples: 1600, bananas: 1440, cherries: -960},
{month: "Q3-2016", apples: 640, bananas: 960, cherries: -640},
{month: "Q4-2016", apples: 320, bananas: 480, cherries: -640},
{month: "Q5-2016", apples: 3840, bananas: 1920, cherries: -1960},
{month: "Q6-2016", apples: 1600, bananas: 1440, cherries: -960},
{month: "Q7-2016", apples: 640, bananas: 960, cherries: -640},
{month: "Q8-2016", apples: 320, bananas: 480, cherries: -640},
{month: "Q9-2016", apples: 3840, bananas: 1920, cherries: -1960},
{month: "Q10-2016", apples: 1600, bananas: 1440, cherries: 960},
{month: "Q11-2016", apples: 640, bananas: 960, cherries: -640},
{month: "Q12-2016", apples: 320, bananas: 480, cherries: -640},
];
var series = d3.stack()
.keys(["apples", "bananas", "cherries"])
.offset(d3.stackOffsetDiverging)
(data);
var margin = {top: 20, right: 30, bottom: 30, left: 60},
width = 900,
height = 500,
legendh = 100, //determines the height of the legend below the chart
padding = 40,
svg = d3.select(".canvas").append('svg').attr('height', height).attr('width',width);
var x = d3.scaleBand()
.domain(data.map(function(d){return d.month;}))
.rangeRound([margin.left, width-margin.right])
.padding(0.1);
var y = d3.scaleLinear()
.domain([d3.min(series, stackMin), d3.max(series, stackMax)])
.rangeRound([height - margin.bottom - legendh, margin.top]);
var colors = ["#66b3ff", "#b3d9ff", "#99ddff", "#99ffdd"];
var z = d3.scaleOrdinal(colors);
//create and call the axes
const xAxis = d3.axisBottom(x);
const yAxis = d3.axisLeft(y);
var chart = svg.append('g').attr('id','chart'); //make a chart group inside the svg
chart.append('g')
.selectAll('g')
.data(series)
.enter().append('g')
.attr('fill', function (d,i) { //because the legend is based on i this should also be based on i
return z(i);
})
.selectAll('rect')
.data(function(d){ return d; })
.enter().append('rect')
.attr('width', x.bandwidth)
.attr('x', function(d){ return x(d.data.month)})
.attr("y", function(d) { return y(d[1]); })
.attr("height", function(d) { return y(d[0]) - y(d[1]); })
chart.append("g")
.attr("transform", "translate(0," + y(0) + ")")
.call(d3.axisBottom(x));
chart.append("g")
.attr("transform", "translate(" + margin.left + ",0)")
.call(d3.axisLeft(y));
var legend = svg.append('g')
.attr('class', 'legend')
.attr('transform', 'translate(' + (padding + 12) + ','+ (height - legendh) + ')');
legend.selectAll('rect')
.data(series)
.enter()
.append('rect')
.attr('x', 0)
.attr('y', function(d,i){
return i * 18;
})
.attr('width', 12)
.attr('height', 12)
.attr('fill', function(d,i){
console.log(z(i));
return z(i);
});
legend.selectAll('text')
.data(series)
.enter()
.append('text')
.text(function(d){
return d.key;
})
.attr('x', 15)
.attr('y', function(d, i){
return i * 18;
})
.attr('text-anchor', 'start')
.attr('alignment-baseline', 'hanging');
function stackMin(serie) {
return d3.min(serie, function(d) { return d[0]; });
}
function stackMax(serie) {
return d3.max(serie, function(d) { return d[1]; });
}
</script>
</body>
</html>