D3-堆叠的条形图-仅使用某些列CSV-计算不同的元素 [英] D3 - Stacked Bar Chart - Only use certain columns CSV - Counting distinct elements

查看:31
本文介绍了D3-堆叠的条形图-仅使用某些列CSV-计算不同的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图弄清楚如何使用D3,但遇到两个问题.一个问题实际上是在CSV文件的某些列中使用数据.另外,在这种情况下,我真正需要CSV的唯一信息是住所"列,学年"列和专业"列.我正在努力使用提供的csv并从本质上使我的程序只读取那些列,而忽略name列和ID列.第二个问题是能够计算每列中不同专业的数量,这是我的柱状图高度,条形图除以某些组.例如,如果我要看一个学生宿舍,我会发现在学生宿舍中,学生宿舍中有8个专业.因此8是栏的高度,子组是学年.在这种情况下,有3名大二学生,2名大一新生,1名大四学生和2名大四学生.因此,单个条形图将相应地分为4类.我假设要计算不同专业的数量,我将使用d3.nest(),然后使用d3.stack()进行堆叠的条形图.

I am trying to figure out how to use D3 and I am having two issues. One problem is essentially using the data in certain columns of my CSV file. Also, the In this case, the only information I really need in the CSV is the Residence column, School Year column, and the Major column. I am struggling to use the provided csv and essentially get my program to read just those columns and ignore the name column, and the ID column. The second issue is being able to count the number of distinct majors in each column and that being my height of the bar and the bar chart is divided by certain groups. For example, if I were to look at one residence hall, I see that in the residence hall, there is a distinct count of 8 majors in the residence hall. So 8 would be the height of the bar and the subgroups would be the school year. In this case, there are 3 Sophomores, 2 freshman, 1 senior, and 2 seniors. So the single bar would be divided into 4 categories accordingly. I am assuming to count the number of distinct majors, I would use d3.nest() and then after use d3.stack() to do the stacked bar graph.

d3.csv("/data/students.csv").then(function(data) {
  console.log(data);
});

CSV:本质上,您是在大学里,有不同学年的各种学生,并且各个专业都居住在某些建筑物中.

CSV: Essentially you are at university where you have various students of different school years, with various majors living in certain buildings .

Name, Residence, ID, School Year, Major
Bill Thornton, Davis Hall, 11123, Sophomore, Mathematics
Savannah Lipscombe, Jameson Hall, 11231, Freshman, Biology
Jay Price, Davis Hall, 12222, Senior, Business
...
Hassan Abdullah, Arthur Hall, 11111, Junior, Mechanical Engineering
Jo Park, Reed Hall, 22123, Freshman, Political Science

推荐答案

按照

As per this question, d3.nest and d3.stack don't work too well together. Instead, you can process your data with vanilla JavaScript into the following format:

[ { Residence: string, [year]: number; } ]

例如

[ { Residence: "Davis Hall", "Sophomore": 1, "Freshman": 2 } ]

然后是堆积的条形图.

您的数据中也有一些空格,这些空格确实存在还是为了可读性而放置在其中?无论如何,我都会删除它们.

You also have some spaces in your data, are those really there or did you put them there for readability? I removed them in any case.

const dataString = `Name, Residence, ID, School Year, Major
Bill Thornton, Davis Hall, 11123, Sophomore, Mathematics
Savannah Lipscombe, Jameson Hall, 11231, Freshman, Biology
Jay Price, Davis Hall, 12222, Senior, Business
Hassan Abdullah, Arthur Hall, 11111, Junior, Mechanical Engineering
Jo Park, Reed Hall, 22123, Freshman, Political Science`.replace(/, /g, ",");

const unique = array => array.filter((v, i) => array.indexOf(v) === i);

const data = d3.csvParse(dataString);
const years = unique(data.map(d => d["School Year"]));
const residences = unique(data.map(d => d.Residence));

const svg = d3.select("svg"),
  margin = {
    top: 35,
    left: 35,
    bottom: 0,
    right: 0
  },
  width = +svg.attr("width") - margin.left - margin.right,
  height = +svg.attr("height") - margin.top - margin.bottom;

const countedData = residences.map(r => {
  const result = {
    Residence: r
  };
  years.forEach(year => {
    result[year] = [];
  });

  data.filter(d => d.Residence === r)
    .forEach(d => {
      result[d["School Year"]].push(d.Major);
    });

  years.forEach(year => {
    result[year] = unique(result[year]).length;
  });
  return result;
});

console.log(countedData);

const x = d3.scaleBand()
  .range([margin.left, width - margin.right])
  .domain(residences)
  .padding(0.1)

const y = d3.scaleLinear()
  .domain([0, d3.max(countedData, d => d3.sum(years.map(y => d[y])))])
  .range([height - margin.bottom, margin.top]);

const z = d3.scaleOrdinal()
  .range(["steelblue", "darkorange", "lightblue"])
  .domain(years);

const xAxis = svg.append("g")
  .attr("transform", `translate(0,${height - margin.bottom})`)
  .attr("class", "x-axis")

const yAxis = svg.append("g")
  .attr("transform", `translate(${margin.left},0)`)
  .attr("class", "y-axis")

svg.selectAll(".y-axis")
  .call(d3.axisLeft(y)
    .ticks(null, "s"))

svg.selectAll(".x-axis")
  .call(d3.axisBottom(x)
    .tickSizeOuter(0))

const stackedData = d3.stack().keys(years)(countedData);
console.log(stackedData);

const group = svg.selectAll("g.layer")
  .data(stackedData, d => d.key)

group.exit().remove()

group.enter()
  .append("g")
  .classed("layer", true)
  .attr("fill", d => z(d.key));

const bars = svg.selectAll("g.layer")
  .selectAll("rect")
  .data(d => d, e => e.data.Residence);

bars.exit().remove()

bars.enter()
  .append("rect")
  .attr("width", x.bandwidth())
  .merge(bars)
  .attr("x", d => x(d.data.Residence))
  .attr("y", d => y(d[1]))
  .attr("height", d => y(d[0]) - y(d[1]));

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="700" height="300"></svg>

这篇关于D3-堆叠的条形图-仅使用某些列CSV-计算不同的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆