我试图用d3绘制个人资料图表。我的数据包含一个约70项措施的小组,范围从3.5到10,每个小节都有一个标签。我想绘制一个图表,以便向上绘制大于6的值,向下绘制6以下。大于6.5的值变为绿色条,低于5.5变为红色。以下是目标图表。
使用以下d3代码,我设法绘制了下面的图表 - 有点像d3的新手。
还有几个问题,我可以向他们寻求帮助: 1.绿色条是高,我想使用3到12的固定范围,图中较高的绿色条的值为7.3,但是达到顶部(10px边距)。 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 :(得分: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。)您无法看到y轴勾选,因为您只通过left.padding
为它们分配了2px:
.attr("transform", "translate(" + padding.left + ", " + padding.top + ")")
事实上,我无法弄清楚填充和边距的相互作用。 classic bar chart example仅使用边距,我会简化并使用该示例。
把这些放在一起,这是一个example。
答案 1 :(得分:2)
在Mark的帮助下,我能够实现我的目标,修正后的代码如下,并对修改提出意见。
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处添加浅灰色水平条,并在图形顶部显示带有适当颜色的标记条形组,以及活动的复合结构侧面和按需显示或隐藏轴。
答案 2 :(得分:0)
从上面的代码和数据开始,我试图用组标签(BRE,CNS等)绘制上部颜色条。我设法绘制了两个不同的条形图(见图片),改变代码如下:
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); });
// 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)。 我考虑过创建一个地图,用于从原始数据中计算最小和最大x的组。
如何为每个d.panel提取最小和最大xScale(d.cell)?我应该循环遍历数组,还是有办法使用d.panel范围对来自xScale(d.cell)的数据进行分组来计算统计数据?