简体   繁体   中英

How to flatten d3.nest using javascript map() method?

I have some data that I've nested with d3. I now want to flatten it. I'm trying to use the map() method to do this, but I am getting errors.

This is the error I'm seeing in my console log -- related to line 24 (where I try to get item.values[i].key ):

Uncaught (in promise) TypeError: Cannot read property 'key' of undefined

I don't see where I'm going wrong and I've spent hours googling. This question is similar, but it wasn't answered. It seems like this should be straightforward.

What am I missing? Thank you!

Here is my code:

<!DOCTYPE html>
<meta charset="utf-8">

<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>

const mhData = axios.get("https://docs.google.com/spreadsheets/d/e/2PACX-1vR-MzpkhMmVMkwmhKFvjPyru5LlYPvWo7_xU8ZARbQmdWP9AIh1VXhZ1aWLWR_PgAySq4gobndfpWP0/pub?gid=0&single=true&output=csv")
    .then(content => {

        const justData = content.data
        const csv = d3.csvParse(justData)

        const nestedData = d3.nest()
            .key(d => d.date)
            .key(d => d.industry)
            .rollup(v => d3.sum(v, d => d.value))
            .entries(csv)
            console.log('nestedData',nestedData)


        const flattenData = nestedData.map((item,i) => ({
            date: item.key,
            industry: item.values[i].key,
            value: item.values[i].value
        }));
        console.log('flattenData',flattenData)
})
</script>
</body>
</html>

In your code: nestedData.map((item,i) => ({... , i is an index of nestedData not values - which is why you are running into errors.

Your nest returns a single level of nesting eg

nestedData [
  {
    "key": "2020-01-07",
    "values": [
      {
        "key": "Tech",
        "value": 1352
      },
      {
        "key": "Media",
        "value": 2848
      },
      ...

So within your map you need a single nested map . You can also change your 'outer' map to flatMap which will then return an array of objects.

I took a small sample of your data to accompany the working example below:

 const csv = mockData(); //console.log(csv); const nestedData = d3.nest().key(d => d.date).key(d => d.industry).rollup(v => d3.sum(v, d => d.value)).entries(csv) //console.log('nestedData',nestedData); const flattenData = nestedData.flatMap((item, i) => { const date = item.key; return item.values.map(industry => ({ date: date, industry: industry.key, value: industry.value })); }); console.log('flattenData', flattenData); function mockData() { const str = `date,industry,gender,value 2020-01-07,Tech,Men,1004 2020-01-07,Tech,Women,348 2020-01-07,Media,Men,2468 2020-01-07,Media,Women,380 2020-01-07,Real Estate,Men,1214 2020-01-07,Real Estate,Women,391 2020-01-14,Tech,Men,989 2020-01-14,Tech,Women,357 2020-01-14,Media,Men,2430 2020-01-14,Media,Women,393 2020-01-14,Real Estate,Men,1322 2020-01-14,Real Estate,Women,366 2020-01-21,Tech,Men,975 2020-01-21,Tech,Women,339 2020-01-21,Media,Men,2416 2020-01-21,Media,Women,388 2020-01-21,Real Estate,Men,1336 2020-01-21,Real Estate,Women,3581`; return d3.csvParse(str); }
 .as-console-wrapper { max-height: 100%;important: top; 0; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>

This isn't a generic way to flatten the output of d3.nest - you would need to consider n levels of nesting and probably need a recursive method. But this should work for your example.

There's some related posts here and here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM