0

I'm having trouble mapping data to the correct output format I need for a d3 stacked bar visualization due to the complexity of the object I'm working with.

My object currently looks like this


arr = {
    reasons: {
           "No supply": 775,
           "More than 1 wk": 773,
           "1 week or less": 1114
    },
    type: "Napkins"
};

I'd like to get the output as a stack array in following form so that I can visualize using stacked bars (note all values are rounded 2 to 2 decimals for simplicity):

stack = {
   0: {
       reason: "No supply"
       startValue: 0
       value: 0.29
       endValue: 0.29
       type: 'Napkins'
   },
   1: {   
       reason: "More than 1 wk"
       startValue: 0.29
       value: 0.28   
       endValue: 0.58
       type: 'Napkins'
   },
   2: {   
       reason: "1 week or less"
       startValue: 0.58
       value: 0.42   
       endValue: 1.0
       type: 'Napkins'
   }
}

I currently have this code to create the stack array but I'm not able to get it populated correctly so I keep getting errors. I believe the mapping here and how I'm accessing the different entries in the array is my problem.

let total = d3.sum(Object.values(arr[1].reasons));  // compute sum across reason values
let value = 0;
let stack = arr.map((d) => ({
          reason: Object.keys(d[1].reasons),
          value: d.value / total,
          startValue: value / total,
          endValue: (value += d.value) / total,
          type: d.type,
        }));

3 Answers 3

2

I think the main issue is you're trying to call .map() on an object instead of an array. To loop through the object you could use a for loop.

arr = {
    reasons: {
           "No supply": 775,
           "More than 1 wk": 773,
           "1 week or less": 1114
         },
    type: "Napkins"
};
const value = 0
const total = 775+773+1114
let stack = [];
for (let d in arr.reasons) {
 let foo = {
   reason: d,
   value: arr.reasons[d] / total,
   startValue: value / total,
   endValue: (value += arr.reasons[d]) / total,
   type: arr.type,
 }
 stack.push(foo)
}
console.log(stack)
Sign up to request clarification or add additional context in comments.

Comments

1
  • To get the total sum, you can use Array.reduce.
  • Using Object.entries, you can get the [key, value] pairs of the object arr.reason.
  • And using Number.toFixed, you can format a number using fixed-point notation.

const arr = {
  reasons: {
    "No supply": 775,
    "More than 1 wk": 773,
    "1 week or less": 1114
  },
  type: "Napkins"
};

const total = Object.values(arr.reasons).reduce((acc, cur) => acc + cur, 0);
let value = 0;
const stack = Object.entries(arr.reasons).map(([key, itemVal]) => ({
  reason: key,
  value: (itemVal / total).toFixed(2),
  startValue: (value / total).toFixed(2),
  endValue: ((value += itemVal) / total).toFixed(2),
  type: arr.type
}));
console.log(stack);

Comments

1
    const reasons = Object.entries(arr.reasons);
    let value = 0;
    reasons.map(([key, value], index) => {
      return (
       index: {
          reason: key,
          value: value / total,
          startValue: value / total,
          endValue: (value += value) / total,
          type: arr.type
        }
       )
    });

Comments

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.