- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有以下csv数据,
date,scanned,unscanned,compid,sbu
01/2014,10,90,101,f&r
02/2014,55,40,101,f&r
03/2014,45,23,101,f&r
04/2014,65,35,101,f&r
05/2014,100,20,101,f&r
06/2014,50,30,101,f&r
07/2014,10,90,101,f&r
08/2014,22,48,101,f&r
09/2014,0,100,101,f&r
10/2014,3,97,101,f&r
11/2014,22,60,101,f&r
12/2014,57,37,101,f&r
01/2014,30,100,101,ip
02/2014,130,10,101,ip
var w = 960,
h = 500,
p = [20, 50, 30, 20],
x = d3.time.scale().range([1, 80]);
y = d3.scale.linear().range([0, h - p[0] - p[2]]),
z = d3.scale.ordinal().range(["#819FF7", "#CB491A"]),
parse = d3.time.format("%m/%Y").parse,
format = d3.time.format("%b-%y");
var xAxis=d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(d3.time.month, 1)
//.ticks(12)
xAxis.tickFormat(d3.time.format("%b-%y"));
/*var yAxis = d3.svg.axis()
.scale(y)
.ticks(12)
.orient("left");*/
var svg = d3.select("#container").append("svg:svg")
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("transform", "translate(" + p[3] + "," + (h - p[2]) + ")");
d3.csv("scandata.csv", function(scan) {
// Transpose the data into layers by cause.
var scantypes = d3.layout.stack()(["scanned", "unscanned"].map(function(scans) {
return scan.map(function(d) {
return {x: parse(d.date), y: +d[scans],z:d.compid,typescan:scans};
});
}));
// Compute the x-domain (by date) and y-domain (by top).
x.domain(scantypes [0].map(function(d) { return d.x; }));
y.domain([0, d3.max(scantypes[scantypes .length - 1], function(d) { return d.y0 + d.y; })]);
// Add a group for each scan.
var cause = svg.selectAll("g.scan")
.data(scantypes)
.enter().append("svg:g")
.attr("class", "scan")
.style("fill", function(d, i) { return z(i); })
.style("stroke", function(d, i) { return d3.rgb(z(i)).darker(); });
// Add a rect for each date.
var rect = cause.selectAll("rect")
.data(Object)
.enter().append("svg:rect")
.attr("id", function(d,i) { return i + " comp " + d.z; })
.attr("x", function(d,i) {
if (i ==0)
{
return x(d.x) ;
}
else
{
return x(d.x);
}} )
.attr("y", function(d) { return -y(d.y0) - y(d.y); })
.attr("height", function(d) { return y(d.y); })
.attr("width", 30)//x.rangeBand()/2
.on("mouseover", function(d){
return tooltip.style("visibility", "visible")
.text((d.y))//d.typescan + " - " +
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 20) + "px"); ;})
.on("mousemove", function(d){
return tooltip.style("visibility", "visible")
.text((d.y)) //d.typescan + " - " +
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 20) + "px"); ;})
.on("mouseout", function(d){return tooltip.style("visibility", "hidden");})
.on("click", function(d){});
var tooltip = d3.select("#container")
.append("div")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "visible")
.text("Scanned vs UnScanned")
.style("font", "Arial")
.style("color", "white")
.style("font-size", "14px");
//Add x-Axis
svg.append("g")
.attr("class", "x axis")
//.attr("transform", function(d) { return "translate(0,80)"; })
.call(xAxis)
// Add a label per date.
var label = svg.selectAll("text")
.data(x.domain())
.enter().append("svg:text")
.attr("x", function(d) { return x(d.x); })//x.rangeBand() / 4
.attr("y", 6)
.attr("text-anchor", "middle")
.attr("dy", ".71em")
.text(format);
// Add y-axis rules.
var rule = svg.selectAll("g.rule")
.data(y.ticks(5))
.enter().append("svg:g")
.attr("class", "rule")
.attr("transform", function(d) { return "translate(0," + -y(d) + ")"; });
rule.append("svg:line")
.attr("x2", w - p[1] - p[3])
.style("stroke", function(d) { return d ? "#fff" : "#000"; })
.style("stroke-opacity", function(d) { return d ? .7 : null; });
rule.append("svg:text")
.attr("x", -15)
.style("font-family","Arial 12px")
.attr("dy", ".25em")
.text(d3.format(",d"));
最佳答案
您似乎对SVG的外观感到困惑,因此不知道如何实现它。
SVG中的条形仅仅是矩形。您需要告诉他们应该放置的位置(通常由栏的左上角定义)以及应该放置的大小。
为了使条形图在堆叠的图中对齐,您需要根据该堆叠的所有值确定它们的位置和大小。
我使用您的数据创建了一个非常简单的堆积条形图示例(只是扫描/未扫描的数据,我没有通过sbu变量将其分开)。
这是工作的example
这是带有注释的代码:
var width = 400;
height = 500;
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var xScale = d3.scale.ordinal()
.rangeRoundBands([0,width], 0.1);
var yScale = d3.scale.linear()
.range([height, 0]);
//note the inverted range, so that small values
//scale to the bottom of the SVG
var data = d3.csv.parse( d3.select("pre#data").text() );
//this just grabs the text from the preformatted block
//and parses it as if it was a csv file
//in your real code, you would use d3.csv(filename, callbackFunction)
//and the rest would be inside your callback function:
xScale.domain( data.map(function(d){return d.date;}) );
//the xScale domain is the list of all categorical values.
//The map function grabs all the date values from the data
//and returns them as a new array.
//I'm not worrying about parsing dates, since
//strings work fine with an ordinal scale
//(although you'd want to parse them if you wanted to reformat them).
yScale.domain( [0,
d3.max(data,
function(d){
return +d.scanned + +d.unscanned;
})
]);
//The yScale domain starts at 0 (since it's a bar chart)
//and goes to the maximum *total* value for each date.
//The d3.max function finds the maximum for an array
//based on the result returned by the function for each
//element of the array. This function just finds the sum
//of the scanned and unscanned values
//(after converting them from strings to numbers with "+").
var dateGroups = svg.selectAll("g")
//create an empty selection of groups
.data(data); //join to the data, each row will get a group
dateGroups.enter().append("g")
//create the actual <g> elements for each row of data
.attr("class", "dateGroup");
//give them a meaningful class
//Now, within each group create a rectangle
//for each category (scanned and unscanned).
//If you had lots of categories, you'd want to
//use a nested selection and a second data join.
//However, to do that you'd need to do a lot of
//data manipulation to create an array of
//separate data objects for each category.
//
//With only two categories, it's easier to just
//do each one separately, and let them inherit
//the data from the parent <g> element.
//For the bottom of the stack:
var bottom = dateGroups.append("rect")
.attr("class", "data scanned");
bottom.attr("y", function(d){
return yScale(+d.scanned);
} )
//y is the TOP of the rectangle
//i.e., the position of this data value
//on the scale
.attr("height", function(d){
return Math.abs( yScale(+d.scanned) - yScale(0) );
//The height of the rectangle is the difference between
//its data value and the zero line.
//Note that the yScale value of zero is
//bigger than the yScale value of the data
//because of the inverted scale, so we use
//absolute value to always get a positive height.
} );
//For the top of the stack:
var top = dateGroups.append("rect")
.attr("class", "data unscanned");
top.attr("y", function(d){
return yScale(+d.unscanned + +d.scanned);
} )
//y is the TOP of the rectangle
//i.e., the position on the scale of
//the *total* of the two data categories
.attr("height", function(d){
return Math.abs( yScale(+d.unscanned) - yScale(0) );
//The height of this bar is just based on
//its value. However, this could also be
//written as
//Math.abs(+yScale(+d.scanned + +d.unscanned)
// - yScale(+d.scanned) )
//i.e., as the difference between the total
//(top of the bar) and the other category's
//value (bottom of the bar)
} );
//The x value and width are the same for both bars
//so we can re-select all the rectangles and
//set these attributes at the same time:
dateGroups.selectAll("rect.data")
.attr("x", function(d){
return xScale(d.date);
})
.attr("width", xScale.rangeBand() );
//don't need a function for width,
//since it doesn't depend on the data
d3.nest
运算符可以将它们组合在一起组成子数组。当堆叠的值与数据表的同一行的数字不同时,您必须使用
forEach()
函数遍历数据的所有行并从每个行构造一个数组。
/*Nest data by date string */
var nestFunction = d3.nest().key( function(d){return d.date;} );
var nestedData = nestFunction.entries(data);
var maxTotal = 0; //maximum count per date,
//for setting the y domain
nestedData.forEach(function(dateGroup) {
//for each entry in the nested array,
//each of which contains all the rows for a given date,
//calculate the total count,
//and the before-and-after counts for each category.
dateGroup.date = dateGroup.key;
//just using the original strings here, but you could
//parse the string date value to create a date object
dateGroup.bars = [];
//create an array to hold one value for each bar
//(i.e., two values for each of the original rows)
var total = 0; //total count per date
dateGroup.values.forEach(function(row) {
//the values array created by the nest function
//contians all the original row data objects
//that match this date (i.e., the nesting key)
//create an object representing the bar for
//the scanned count, and add to the bars array
dateGroup.bars.push(
{date:dateGroup.date,
type: "scanned",
count: +row.scanned,
compid: row.compid,
sbu: row.sbu,
y0: total, //total value *before* this bar
y1: (total = total + +row.scanned) //new total
}
);
//create an object representing the bar for
//the UNscanned count, and add to the bars array
dateGroup.bars.push(
{date:dateGroup.date,
type: "unscanned",
count: +row.unscanned,
compid: row.compid,
sbu: row.sbu,
y0: total, //total value *before* this bar
y1: (total = total + +row.unscanned) //new total
}
);
});
maxTotal = Math.max(maxTotal, total); //update max
});
compid
的值保留在不同的堆叠中),则可以将该参数作为嵌套函数的第二个键。如果值在所有嵌套键上都匹配,则嵌套在一起。当然,那么您还必须修改x比例,以通过两个键将堆栈分开。查找分组条形图的示例以了解如何执行此操作。
<g>
元素,然后在每个组中创建矩形的嵌套选择,然后将内部数组(条形数据)连接到该数组:
var dateGroups = svg.selectAll("g")
//create an empty selection of groups
.data(nestedData); //join to the data,
//each nested object (i.e., date) will get a group
dateGroups.enter().append("g")
//create the actual <g> elements for each row of data
.attr("class", "dateGroup");
//give them a meaningful class
//Now, within each group create a rectangle
//for each category from the "bars" array created earlier.
//This uses a nested selection, since we don't know
//how many bars there will be for a given date.
var bars = dateGroups.selectAll("rect")
.data( function(d) {return d.bars;})
//the 'd' value passed in is the data for each
//dateGroup, each of which will now have a
//nested selection of bars
bars.enter().append("rect"); //create the rectangles
bars.attr("class", function(d){
//assign classes for all the categorical values
//(after stripping out non-word characters)
//so they can be styled with CSS
var specialchars = /\W+/g;
//regular expression to match all non-letter, non-digit characters
return ["data",
"type-" + d.type.replace(specialchars, ""),
"compid-" + d.compid.replace(specialchars, ""),
"sbu-" + d.sbu.replace(specialchars, "")
].join(" "); //class list is space-separated
})
.attr("y", function(d){
return yScale(d.y1);
//y is the TOP of the rectangle
//i.e., the position of the *total* value
//for this bar and all others under it in the stack
} )
.attr("height", function(d){
return Math.abs( yScale(d.y1) - yScale(d.y0) );
//the height of the rectangle is the difference
//between the total *after*
//this value is added to the stack
// (top of the bar, y1)
//and the total *before* it is added
// (bottom of the bar, y0)
//Since this is a linear scale, this could also
//be written as
//Math.abs( yScale(d.count) - yScale(0) )
//i.e., as the difference between
//its data value and zero line.
//Note the use of absolute value to
//compensate for a possibly inverted scale.
} )
.attr("x", function(d){
return xScale(d.date);
})
.attr("width", xScale.rangeBand() )
//don't need a function for width,
//since it doesn't depend on the data
.append("title") //add a tooltip title
.text(function(d) {
return d.sbu + ", " +d.type +":" + d.count;
});
关于d3.js-堆叠的条形图中的第2组数据值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21522825/
我想做的是让 JTextPane 在 JPanel 中占用尽可能多的空间。对于我使用的 UpdateInfoPanel: public class UpdateInfoPanel extends JP
我在 JPanel 中有一个 JTextArea,我想将其与 JScrollPane 一起使用。我正在使用 GridBagLayout。当我运行它时,框架似乎为 JScrollPane 腾出了空间,但
我想在 xcode 中实现以下功能。 我有一个 View Controller 。在这个 UIViewController 中,我有一个 UITabBar。它们下面是一个 UIView。将 UITab
有谁知道Firebird 2.5有没有类似于SQL中“STUFF”函数的功能? 我有一个包含父用户记录的表,另一个表包含与父相关的子用户记录。我希望能够提取用户拥有的“ROLES”的逗号分隔字符串,而
我想使用 JSON 作为 mirth channel 的输入和输出,例如详细信息保存在数据库中或创建 HL7 消息。 简而言之,输入为 JSON 解析它并输出为任何格式。 最佳答案 var objec
通常我会使用 R 并执行 merge.by,但这个文件似乎太大了,部门中的任何一台计算机都无法处理它! (任何从事遗传学工作的人的附加信息)本质上,插补似乎删除了 snp ID 的 rs 数字,我只剩
我有一个以前可能被问过的问题,但我很难找到正确的描述。我希望有人能帮助我。 在下面的代码中,我设置了varprice,我想添加javascript变量accu_id以通过rails在我的数据库中查找记
我有一个简单的 SVG 文件,在 Firefox 中可以正常查看 - 它的一些包装文本使用 foreignObject 包含一些 HTML - 文本包装在 div 中:
所以我正在为学校编写一个 Ruby 程序,如果某个值是 1 或 3,则将 bool 值更改为 true,如果是 0 或 2,则更改为 false。由于我有 Java 背景,所以我认为这段代码应该有效:
我做了什么: 我在这些账户之间创建了 VPC 对等连接 互联网网关也连接到每个 VPC 还配置了路由表(以允许来自双方的流量) 情况1: 当这两个 VPC 在同一个账户中时,我成功测试了从另一个 La
我有一个名为 contacts 的表: user_id contact_id 10294 10295 10294 10293 10293 10294 102
我正在使用 Magento 中的新模板。为避免重复代码,我想为每个产品预览使用相同的子模板。 特别是我做了这样一个展示: $products = Mage::getModel('catalog/pro
“for”是否总是检查协议(protocol)中定义的每个函数中第一个参数的类型? 编辑(改写): 当协议(protocol)方法只有一个参数时,根据该单个参数的类型(直接或任意)找到实现。当协议(p
我想从我的 PHP 代码中调用 JavaScript 函数。我通过使用以下方法实现了这一点: echo ' drawChart($id); '; 这工作正常,但我想从我的 PHP 代码中获取数据,我使
这个问题已经有答案了: Event binding on dynamically created elements? (23 个回答) 已关闭 5 年前。 我有一个动态表单,我想在其中附加一些其他 h
我正在尝试找到一种解决方案,以在 componentDidMount 中的映射项上使用 setState。 我正在使用 GraphQL连同 Gatsby返回许多 data 项目,但要求在特定的 pat
我在 ScrollView 中有一个 View 。只要用户按住该 View ,我想每 80 毫秒调用一次方法。这是我已经实现的: final Runnable vibrate = new Runnab
我用 jni 开发了一个 android 应用程序。我在 GetStringUTFChars 的 dvmDecodeIndirectRef 中得到了一个 dvmabort。我只中止了一次。 为什么会这
当我到达我的 Activity 时,我调用 FragmentPagerAdapter 来处理我的不同选项卡。在我的一个选项卡中,我想显示一个 RecyclerView,但他从未出现过,有了断点,我看到
当我按下 Activity 中的按钮时,会弹出一个 DialogFragment。在对话框 fragment 中,有一个看起来像普通 ListView 的 RecyclerView。 我想要的行为是当
我是一名优秀的程序员,十分优秀!