Search code examples
javascriptrecharts

Getting data in the correct recharts format for a monthly bar chart view


I have some data which looks like so:

data = [
{'id': 1, 'fields': {'name': 'name-1', 'team': 'team-1', 'date': '2022-04-01'}},
{'id': 2, 'fields': {'name': 'name-2', 'team': 'team-2', 'date': '2022-04-02'}},
{'id': 3, 'fields': {'name': 'name-3', 'team': 'team-3', 'date': '2022-04-03'}},
{'id': 4, 'fields': {'name': 'name-4', 'team': 'team-1', 'date': '2022-04-02'}},
{'id': 5, 'fields': {'name': 'name-5', 'team': 'team-2', 'date': '2022-04-02'}},

]

What I am trying to do is get it in the format so I can visualize it with recharts. What I am going for is something like this: Monthly chart example

I have been able to get the data into a format where I have counted all the unique teams by doing:

  const counts = {};
  data.forEach(function (x) {counts[x.fields['team']] = (counts[x.fields['team']] || 0) + 1;});

which gives me the format of:

{'team-1': 2, 'team-2': 2, 'team-3': 1}

and I have been able to get all the items in a given month by doing:

const monthCountArr = new Array(12).fill(0);
data.forEach(({ fields }) => monthCountArr[new Date(fields['date']).getMonth()] += 1);

which yields:

[{0: 0, 1: 0, 2: 0: 3: 5, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0, 10: 0, 11: 0}]

but, now I am not so sure how to approach the rest of this problem so I can get the chart to show how many people are in each team for a given month.

I am not even sure what kind of a format I need? maybe something like this:

data = [
{'month': 'Apr', 'teams': {'team-1': 2, 'team-2': 2, 'team-3': 1}}

]

then I could plot three different bars (one for each team) and their respective values all under the month of April which would be on the X-axis.

I don't know, I've been going at this for hours and I just cannot figure out how to proceed.

The recharts documentation has an example where there data is like this:

const data = [
  {
    name: 'Page A',
    uv: 4000,
    pv: 2400,
    amt: 2400,
  },
  {
    name: 'Page B',
    uv: 3000,
    pv: 1398,
    amt: 2210,
  },
  {
    name: 'Page C',
    uv: 2000,
    pv: 9800,
    amt: 2290,
  },
  {
    name: 'Page D',
    uv: 2780,
    pv: 3908,
    amt: 2000,
  },
  {
    name: 'Page E',
    uv: 1890,
    pv: 4800,
    amt: 2181,
  },
  {
    name: 'Page F',
    uv: 2390,
    pv: 3800,
    amt: 2500,
  },
  {
    name: 'Page G',
    uv: 3490,
    pv: 4300,
    amt: 2100,
  },
];

so maybe I need my data in this format:

data = [
{'month': 'April', 
'team-1': 2,
'team-2': 2,
'team-3': 1}
]


Solution

  • I would go around and transform data as follows;

    import "./styles.css";
    import React from "react";
    import {
      BarChart,
      Bar,
      XAxis,
      YAxis,
      CartesianGrid,
      Tooltip,
      Legend
    } from "recharts";
    
    const rawData = [
      { id: 1, fields: { name: "name-1", team: "team-1", date: "2022-04-01" } },
      { id: 2, fields: { name: "name-2", team: "team-2", date: "2022-04-02" } },
      { id: 3, fields: { name: "name-3", team: "team-3", date: "2022-04-03" } },
      { id: 4, fields: { name: "name-4", team: "team-1", date: "2022-04-02" } },
      { id: 5, fields: { name: "name-5", team: "team-2", date: "2022-04-02" } }
    ];
    
    
    // get unique list of teams in order to tell recharts to understand as a bar
    const teams = Array.from(new Set(rawData.map((i) => i.fields.team)));
    
    /*
    Shape the data in the following form;
    {
      date: '2022-12-22', <- this will be taken as the X axis
      'team-1': 1, <- each team data will be taken as the bar height
      'team-2': 2
    }
    
    */
    const data = Object.values(
      rawData.reduce((acc, d) => {
        const {
          fields: { date, team }
        } = d;
        acc[date] = acc[date] || { date };
        acc[date][team] = (acc[date][team] || 0) + 1;
        return acc;
      }, {})
    );
    
    export default function App() {
      return (
        <BarChart
          width={500}
          height={300}
          data={data}
          margin={{
            top: 5,
            right: 30,
            left: 20,
            bottom: 5
          }}
        >
          <CartesianGrid strokeDasharray="3 3" />
          <XAxis dataKey="date" />
          <YAxis />
          <Tooltip />
          <Legend />
          {teams.map((t) => (
            <Bar dataKey={t} />
          ))}
        </BarChart>
      );
    }
    

    It will produce follwing result; simple bar chart