1

I have the following arrays that a want to display as a stacked bar chart with p5js (javascript).

Below you can see an arrayOfMonths (month1, month2,...) that is going to be displayed on the X Axis of the Stacked Bar Chart. Now, Each month has a number of other (0-to many) elements. Those are the elements that I want to display on Y Axis so for example month1 has 2 elements i want to create two rectangles on the first element on X Axis and so on as shown below:

4|     ▭

3|     ▭   ▭

2| ▭  ▭    ▭

1| ▭  ▭ ▭ ▭
▬▬▬▬▬▬▬▬▬▬▬▬▬▬
   m1 m2 m3 m4

let me know if you know how to handle 2Dimensional Arrays :) Thanks...

/* Needed Variables Declaration */
var month1 = ["M01V01","M01V02"];
var month2 = ["M02V01","M02V02","M02V03","M02V04"];
var month3 = ["M03V01"];
var month4 = ["M04V01","M04V02","M04V03"];
var arrayOfMonths = [month1,month2,month3,month4];
var arrayOfResponses = ["1", "2", "3","4","5"];

function addValues(){

	var locX = canvasWidth-(canvasWidth-125);
  var locY = canvasHeight-25;
  var barWidth = 50; 
  var barData = canvasHeight/(numOfResponses+2);
  
  for(var x=0; x<arrayOfMonths.length; x++){
    /* Draw Stack Bars (rectangles) */
    for(var y=0; y<arrayOfMonths[x].length; y++){
      
      
      /* ADD TEXT TO X AXIS */
      if(y<=x){
        
      	locX = canvasWidth-(canvasWidth-125);
        locY -= 125;
        text(arrayOfMonths[x][y], locX, locY);
        
        fill(random(255),random(255),random(255));
	    	rect(locX, locY, barWidth, barData);
      }
      //	locX+=canvasWidth/(numOfMonths+1);
      
  		locX+=100;    
			
      //locY -= 150;	
    }
    //locX = canvasWidth-(canvasWidth-125);  
    //locY = canvasHeight-210;
  }
}

5
  • What errors are you getting ? Commented Apr 13, 2018 at 14:06
  • related : stackoverflow.com/questions/29464535/… Commented Apr 13, 2018 at 14:08
  • Im not getting any errors i just want to display the array of elements correctly on the graph.. Basically, Lets say the 1st element in the array has two values in it, I want to draw the rectangles one above each other and then continue on the next element in the array by changing the location.. More information in the function (method) addValues at the end of the javascript file. Commented Apr 13, 2018 at 14:11
  • Sorry, but your question is pretty unclear. The code you posted already uses a nested for loop to iterate over all of the elements in your array. Can you please post a simplified minimal reproducible example instead of your full program? Commented Apr 13, 2018 at 16:17
  • I have edited my question please let me know if its more clear now Commented Apr 13, 2018 at 17:13

1 Answer 1

1

Based on your data this is one way you could do it. You could map number of elements on x and y axes to size of your graph or size of those axes, so each index is scaled between 0 - data.length and start - end of axis. You could also use first element of xTicks for space size between them and then you just draw axes based on that data.

And for data you just loop xData which is 2D array and use current index for x and y position from xTicks and yTicks. You also need to adjust rects a bit (+ - 5) which is half of 10, and same for ticks text.

Note that y position of rects is based on its index in months array and not on its text so for example if you have var month1 = ["M01V03", "M01V04"] it will still be on first two y position, instead you could take last char of text Fiddle

var month1 = ["M01V01", "M01V02"];
var month2 = ["M02V01", "M02V02", "M02V03", "M02V04"];
var month3 = ["M03V01"];
var month4 = ["M04V01", "M04V02", "M04V03"];
var months = [month1, month2, month3, month4];
var responses = ["1", "2", "3", "4", "5"];

let graph;

function setup() {
  createCanvas(400, 250);
  graph = new Graph(months, responses, 200, 300);
}

function draw() {
  background(50, 50, 150);
  graph.show();
  graph.showData();
}

class Graph {
  constructor(xData, yData, height, width) {
    this.xData = xData;
    this.yData = yData;
    this.height = height;
    this.width = width;
    this.xStart = 60;
    this.yStart = window.height - 30;

    this.xTicks = this.xData.map((e, i) => {
      return map(i, 0, this.xData.length, this.xStart, this.width);
    })

    this.yTicks = this.yData.map((e, i) => {
      return map(i, 0, this.yData.length, this.yStart - this.height, this.yStart);
    })

    this.xSpace = this.xTicks[0];
  }

  show() {
    this.xAxis();
    this.yAxis();
  }

  xAxis() {
    stroke(255);
    strokeWeight(1);
    line(this.xStart, this.yStart, this.xStart + this.width, this.yStart);
    strokeWeight(2)
    this.xTicks.forEach((x, i) => {
      stroke(255)
      line(x + this.xSpace, this.yStart + 2, x + this.xSpace, this.yStart - 2)
      noStroke()
      fill(255);
      text(`m${i + 1}`, x + this.xSpace - 7, this.yStart + 14)
    })
  }

  yAxis() {
    stroke(255);
    strokeWeight(1);
    line(this.xStart, this.yStart, this.xStart, this.yStart - this.height);
    strokeWeight(2)
    this.yTicks.forEach((y, i) => {
      stroke(255)
      line(this.xStart - 2, this.yStart - y, this.xStart + 2, this.yStart - y);
      noStroke()
      fill(255);
      textSize(10)
      text(this.yData[i], this.xStart - 15, this.yStart - y + 3)
    })
  }

  showData() {
    this.xData.forEach((arr, i) => {
      arr.forEach((item, j) => {
        noFill();
        stroke(255);
        rect(this.xTicks[i] + this.xSpace - 5, this.yStart - this.yTicks[j] - 5, 10, 10)
      })
    })
  }

}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.11/p5.min.js"></script>

Sign up to request clarification or add additional context in comments.

2 Comments

thanks, that pretty much explains it better in my brain ;) have a nice day
Glad I could help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.