2014-12-24 3 views
0

Я пытаюсь нарисовать диаграмму профиля с d3. Мои данные содержат панель из примерно 70 мер в диапазоне от 3,5 до 10 и метку для каждого бара. Я хотел бы нарисовать диаграмму так, чтобы значения больше 6 были подняты вверх и ниже 6 вниз. Значения, превышающие 6.5, становятся зелеными полосами, ниже 5,5 оборотов до красного. Ниже приведена диаграмма. enter image description hereРисование диаграммы профиля (бар) с d3

Используя следующий код d3, мне удалось нарисовать график ниже - бит был немного новым для d3. enter image description here

Есть несколько вопросов, по-прежнему, для которых я спрашиваю некоторую помощь: 1. Полоски являются высокими, я хотел бы использовать фиксированный диапазон от 3 до 12, чем выше зеленая полоса на графике имеет значение 7.3 и, тем не менее, достигает вершины (10px margin). 2. Я не могу отобразить значения оси y, я бы хотел отобразить 3, 6 и 9. 3. x и y-оси слишком толстые, я бы предпочел 1px. 4. Некоторые бары на панели могут не иметь значения, я бы хотел, чтобы они отображались в виде пустых баров.

Начиная с кода ниже, что делать? Где я ошибся с отображением оси. Любая помощь будет оценена по достоинству.

function draw(data) { 

    data.forEach(function(d) { 
      d.value = d.value - 6.0; 
     }); 

var margin = { top: 10, right: 10, bottom: 80, left: 50 }, 
    padding = { top: 2, right: 2, bottom: 2, left: 2 }, 
    width = 960 - margin.left - margin.right - padding.left - padding.right, 
    height = 240 - margin.top - margin.bottom - padding.top - padding.bottom; 

var xScale = d3.scale.ordinal() 
    .rangeRoundBands([0, width], .2); 

var yScale = d3.scale.linear() 
    .range([height - padding.top - padding.bottom, 0]) 
    .domain([-3, 6]); 

var xAxis = d3.svg.axis() 
    .scale(xScale) 
    .orient("bottom") 
    .ticks(function(d) { return d.label; }); 

var yAxis = d3.svg.axis() 
    .scale(yScale) 
    .orient("left") 
    .ticks(yScale([3,6,9])); 

xScale.domain(data.map(function(d) { return d.label; })); 
yScale.domain(d3.extent(data, function(d) { return d.value; })); 

var svg = d3.select("#chart").append("svg:svg") 
    .attr("width", width + margin.left + margin.right) 
    .attr("height", height + margin.top + margin.bottom); 

svg.append("g") 
    .attr("class", "axis") 
    .attr("transform", "translate("+padding.top+"," + (height-padding.bottom) + ")") 
    .call(xAxis) 
    .selectAll("text") 
    .style("text-anchor", "end") 
    .attr("dx", "-.8em") 
    .attr("dy", ".15em") 
    .attr("transform", "rotate(-50)"); 

svg.append("g") 
    .attr("class", "axis") 
    .attr("transform", "translate("+padding.left+", "+padding.top+")") 
    .call(yAxis) 

svg.selectAll("bar") 
    .data(data) 
    .enter().append("rect") 
    .attr("x", function(d) { return xScale(d.label); }) 
    .attr("y", function(d) { return yScale(d3.max([0, d.value])); }) 
    .attr("width", xScale.rangeBand()) 
    .attr("height", function(d) { return Math.abs(yScale(d.value)-yScale(0)); }) 
    .style("fill", function(d) { 
      if(d.value < -0.5) { return "red"; } 
      else if (d.value > 0.5) { return "green"; } 
      else { return "lightgray"; } 
     }); 
} 
+0

Можете ли вы обновить свой вопрос с помощью выборочных данных? – Mark

ответ

2

С большой помощью Марк, я был в состоянии достичь своей цели, исправленный код ниже с комментариями модификаций. enter image description here

код D3:

function draw(data) { 

// padding was removed 
// data is no more shifted by 6, graph is centered on 6 instead. 
var margin = { top: 0, right: 0, bottom: 100, left: 20 }, 
    width = 960 - margin.left - margin.right, 
    height = 240 - margin.top - margin.bottom; 

var xScale = d3.scale.ordinal() 
    .rangeRoundBands([0, width], .2); 

// removed extend on scaling which forced bars to span on the whole height 
// since original data is scaled from 4 to 10, I'd like the bar reflect absolute values 
var yScale = d3.scale.linear() 
    .range([height, 0]) 
    .domain([3, 10]); 

var xAxis = d3.svg.axis() 
    .scale(xScale) 
    .orient("bottom") 
    .ticks(function(d) { 
      return d.cell; 
      }); 

// tickValues have been added to force proper ticks on y-axis 
var yAxis = d3.svg.axis() 
    .scale(yScale) 
    .orient("left") 
    .tickValues([3, 6, 9]); 

xScale.domain(data.map(function(d) { 
         return d.cell; 
         })); 

// transform attribute was added to shift the whole graph by margin.left 
// this explains why the y-axis and ticks were not visible 
var svg = d3.select("#chart").append("svg") 
    .attr("width", width + margin.left + margin.right) 
    .attr("height", height + margin.top + margin.bottom) 
    .append("g") 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

svg.append("g") 
    .attr("class", "axis") 
    .attr("transform", "translate(0," + height + ")") 
    .call(xAxis) 
    .selectAll("text") 
    .style("text-anchor", "end") 
    .attr("dx", "-.8em") 
    .attr("dy", ".15em") 
    .attr("transform", "rotate(-50)"); 

svg.append("g") 
    .attr("class", "axis") 
    .call(yAxis) 
.append("text") 
.attr("transform", "rotate(-90)") 
.attr("y", 6) 
.attr("dy", ".71em") 
.style("text-anchor", "end") 
.text("-log(GI50) uM"); 

// y-scale is now centered on 6, greater draws upward, lesser draws downward 
// color is set using a CSS with [5, 7] range set to gray 
svg.selectAll("bar") 
    .data(data) 
    .enter().append("rect") 
    .attr("class", function(d) { 
     if (d.value < 5) { return "bar negative"; } 
     else if (d.value > 7) { return "bar positive"; } 
     else { return "bar neutral"; } 
     }) 
    .attr("x", function(d) { return xScale(d.cell); }) 
    .attr("y", function(d) { return yScale(d3.max([6, d.value])); }) 
    .attr("width", xScale.rangeBand()) 
    .attr("height", function(d) { return Math.abs(yScale(d.value)-yScale(6)); }); 
} 

CSS используется:

.bar.positive { 
    fill: #1a9641; 
} 

.bar.negative { 
    fill: #d7191c; 
} 

.bar.neutral { 
    fill: #d5d5d5; 
} 

.axis text { 
    font-family: sans-serif; 
    font-size: 11px; 
} 

.axis path { 
    stroke-width: 1px; 
    fill: none; 
    stroke: black; 
} 

.axis line { 
    stroke-width: 1px; 
    fill: none; 
    stroke: #000; 
    shape-rendering: crispEdges; 
} 

.chart { 
    padding-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; 
    background: transparent; 
    width: 960px; 
    height: 240px; 
} 

Некоторые данные:

[ { 
"panel" : "BRE", 
"cell" : "BT-549", 
"value" : 5.846 
} ], [ { 
"panel" : "BRE", 
"cell" : "HS 578T", 
"value" : 5.429 
} ], [ { 
"panel" : "BRE", 
"cell" : "MCF7", 
"value" : 5.953 
} ], [ { 
"panel" : "BRE", 
"cell" : "MDA-MB-231/ATCC", 
"value" : 5.669 
} ], [ { 
"panel" : "BRE", 
"cell" : "MDA-MB-435", 
"value" : 5.804 
} ], [ { 
"panel" : "BRE", 
"cell" : "MDA-N", 
"value" : 5.828 
} ], [ { 
"panel" : "BRE", 
"cell" : "NCI/ADR-RES", 
"value" : 5.575 
} ], [ { 
"panel" : "BRE", 
"cell" : "T-47D", 
"value" : 5.959 
} ], [ { 
"panel" : "CNS", 
"cell" : "SF-268", 
"value" : 5.556 
} ], [ { 
"panel" : "CNS", 
"cell" : "SF-295", 
"value" : 5.14 
} ], [ { 
"panel" : "CNS", 
"cell" : "SF-539", 
"value" : 5.431 
} ], [ { 
"panel" : "CNS", 
"cell" : "SNB-19", 
"value" : 4.884 
} ], [ { 
"panel" : "CNS", 
"cell" : "SNB-75", 
"value" : 5.465 
} ], [ { 
"panel" : "CNS", 
"cell" : "U251", 
"value" : 5.317 
} ] 

Следующий шаг будет добавить полосы ошибок и масштабирование соответствующим образом, добавить свет серых горизонтальных полос на 5, 7 и 9 и отображать маркированные группы баров o n вершина графика, с соответствующими цветами, а также структура активного соединения на стороне и отображение по требованию или скрыть оси.

enter image description here

3

Я смущен вашим кодом.

1.) Вы заявляете вы хотите определенный домен [3, 12], но в вашем yScale сначала установите его в domain([-3, 6]); а затем сбросить его в мин/макс с помощью d3.extent. Зачем?

2.) В чем цель d.value = d.value - 6.0;, разве вам лучше не оставлять свои данные в покое, а затем делать сравнения для цвета вокруг 6. Вместо того, чтобы пытаться сопоставить его с 0 и сравнивать вокруг этого?

3.) Вы можете настроить внешний вид оси через CSS. Для того, что вы хотите использовать:

.axis path { 
    stroke-width: 1px; 
    fill: none; 
    stroke: black; 
} 

4.) Вы не можете видеть вашу ось у клеща, потому что вы только выделили 2px к ним через left.padding:

.attr("transform", "translate(" + padding.left + ", " + padding.top + ")") 

На самом деле, я могу Не задумывайтесь о том, как вы будете взаимодействовать с заполнением и полями. classic bar chart example просто использует поля, я бы упростил и просто использовал этот пример.

Взяв все это вместе, вот example.

enter image description here

+0

Действительно, 3, 12 - это исходный диапазон, а -3,6 - данные дерьма в центре на 6. Я не знал о степени, это должно быть одной из проблем. Благодарю. Пункт 2, -6 ahas установлен, чтобы убедиться, что значение ниже 6 идет вниз. В самом деле, если бы я мог предоставить данные как есть, это было бы предпочтительнее, я бы предпочел, чтобы я пробовал многое перед тем, как спросить. Идея дополнения заключалась в том, чтобы убедиться, что бары останавливают 2px перед осями ... чисто эстетичны. Мне действительно не удалось получить то, что я ожидал. Спасибо за вашу помощь. – Pierre

0

Начиная от приведенного выше кода и данных, я пытаюсь нарисовать верхнюю цветную полосу с группой тегов (BRE, ЦНС и т.д.). Мне удалось сделать два различных бара (см фотографии) изменение кода как следующие:

nodeEnter 
    .append("rect") 
    .attr("x", function(d) { return lScale(d.cell); }) 
    .attr("y", 0) 
    .attr("width", lScale.rangeBand()) 
    .attr("height", 15) 
    .attr("style", function(d) { return "fill:"+color(d.panel); }); 

enter image description here

// create a specific scaling function for the x-axis with a reduced spacing between bars 
var lScale = d3.scale.ordinal() 
    .rangeRoundBands([0, width], 1e-6); 

nodeEnter 
    .append("rect") 
    .attr("x", function(d) { return lScale(d.cell); }) 
    .attr("y", 0) 
    .attr("width", lScale.rangeBand()) 
    .attr("height", 15) 
    .attr("style", function(d) { return "fill:"+color(d.panel); }); 

Я хотел бы создать панель без пробелов между полосами того же цвета и разделение между группами (разный цвет) и добавление имени группы (d.panel) в центр бара. Я думал о создании карты для групп, вычисляющих min и max на x из исходных данных.

Как извлечь min и max xScale (d.cell) для каждого d.панели? Должен ли я проходить через массив или есть способ использовать диапазон d.panel для группировки данных из xScale (d.cell) для вычисления статистики?

enter image description here

Смежные вопросы