Reputation: 41
I'm using D3 and having trouble getting my data nested the way I need. I'll try to simplify the scenario to its essence for this question.
I have expense data saved to variable expenses
. Each object in the array represents a single purchase on a particular date at a particular brick-and-mortar store. ("StoreID" is unique; for brevity I'm omitting street address):
// original data
var expenses =
[
{"storeID":"4872379","storeName":"Gap","zipCode":"10032","amount":34.88,"date":"11/12/2015"},
{"storeID":"4872379","storeName":"Gap","zipCode":"10032","amount":-34.88,"date":"11/15/2015"},
{"storeID":"2209875","storeName":"Banana Republic","zipCode":"10003","amount":1650.54,"date":"12/01/2015"},
{"storeID":"5434432","storeName":"Gap","zipCode":"10031","amount":120.11,"date":"11/18/2015"},
{"storeID":"5434432","storeName":"Gap","zipCode":"10031","amount":45.5,"date":"12/01/2015"},
{"storeID":"5434432","storeName":"Gap","zipCode":"10031","amount":117.08,"date":"12/01/2015"}
]
What I want to do is group amount
/date
pairs as objects in a single array for each unique store. This is what I'd like to end up with:
// desired structure
[
{"key":"2209875",
"storeName":"BananaRepublic",
"zipCode":"10003",
"values": [
{"amount":1650.54,
"date":"12/01/2015"}]
},
{"key":"4872379",
"storeName":"Gap",
"zipCode":"10032",
"values": [
{"amount":34.88,
"date":"11/12/2015"},
{"amount":-34.88,
"date":"11/15/2015"}]
},
{"key":"5434432",
"storeName":"Gap",
"zipCode":"10031",
"values": [
{"amount":120.11,
"date":"11/18/2015"},
{"amount":45.5,
"date":"12/01/2015"},
{"amount":117.08,
"date":"12/01/2015"}]
}
]
Using d3.nest(), I'm only able to get this far:
// getting closer
var expensesByStoreID = d3.nest()
.key(function(d) { return d.storeID; })
.entries(expenses);
// expensesByStoreID holds this:
[
{"key":"2209875",
"values": [
{"storeID":"2209875",
"storeName":"BananaRepublic",
"zipCode":"10003",
"amount":1650.54,
"date":"12/01/2015"}]
},
{"key":"4872379",
"values": [
{"storeID":"4872379",
"storeName":"Gap",
"zipCode":"10032",
"amount":34.88,
"date":"11/12/2015"},
{"storeID":"4872379",
"storeName":"Gap",
"zipCode":"10032",
"amount":-34.88,
"date":"11/15/2015"}]
},
{"key":"5434432",
"values": [
{"storeID":"5434432",
"storeName":"Gap",
"zipCode":"10031",
"amount":120.11,
"date":"11/18/2015"},
{"storeID":"5434432",
"storeName":"Gap",
"zipCode":"10031",
"amount":45.5,
"date":"12/01/2015"},
{"storeID":"5434432",
"storeName":"Gap",
"zipCode":"10031",
"amount":117.08,
"date":"12/01/2015"}]
}
]
Each amount
and date
are together in an object but the store details are also there, repeatedly. I want the store details stored just once per store object. It becomes an efficiency problem because the database contains many thousands of stores and purchases.
Is there something I can change in my d3.nest() code? Is there a plain Javascript function that would be able to turn my data structure from "original" to "desired"? Any help would be appreciated. :-)
Upvotes: 1
Views: 82
Reputation: 41
Actually, this gives me the structure I was looking for:
var data = expensesByStoreID.map(function(d) {
return {storeID: d.key,
storeName: d.values[0].storeName,
zipCode: d.values[0].zipCode,
values: d.values.map(function(k) {
return { amount: k.amount,
date: k.date
}
})
}
})
document.body.appendChild(document.createElement('pre')).innerHTML = JSON.stringify(data, null, 2)
[
{
"storeID": "2209875",
"storeName": "Banana Republic",
"zipCode": "10003",
"values": [
{
"amount": 1650.54,
"date": "12/01/2015"
}
]
},
{
"storeID": "4872379",
"storeName": "Gap",
"zipCode": "10032",
"values": [
{
"amount": 34.88,
"date": "11/12/2015"
},
{
"amount": -34.88,
"date": "11/15/2015"
}
]
},
{
"storeID": "5434432",
"storeName": "Gap",
"zipCode": "10031",
"values": [
{
"amount": 120.11,
"date": "11/18/2015"
},
{
"amount": 45.5,
"date": "12/01/2015"
},
{
"amount": 117.08,
"date": "12/01/2015"
}
]
}
]
Upvotes: 0
Reputation: 32327
You can do like this:
var expenses =
[
{"storeID":"4872379","storeName":"Gap","zipCode":"10032","amount":34.88,"date":"11/12/2015"},
{"storeID":"4872379","storeName":"Gap","zipCode":"10032","amount":-34.88,"date":"11/15/2015"},
{"storeID":"2209875","storeName":"Banana Republic","zipCode":"10003","amount":1650.54,"date":"12/01/2015"},
{"storeID":"5434432","storeName":"Gap","zipCode":"10031","amount":120.11,"date":"11/18/2015"},
{"storeID":"5434432","storeName":"Gap","zipCode":"10031","amount":45.5,"date":"12/01/2015"},
{"storeID":"5434432","storeName":"Gap","zipCode":"10031","amount":117.08,"date":"12/01/2015"}
];
expensesByStoreID = d3.nest()
.key(function(d) {
return d.storeID;//group by store id
})
.entries(expenses);
//now designing the data output of nest into your desired format
var data = expensesByStoreID.map(function(d) {
return {
key: {
storeID: d.key,//changing the key structure
storeName: d.values[0].storeName,
zipCode: d.values[0].zipCode
},
values: d.values.map(function(k) {
return {
amount: k.amount, //changing the values structure
date: k.date
}
})
};
})
console.log(data);
document.body.appendChild(document.createElement('pre')).innerHTML = JSON.stringify(data, null, 2)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
Upvotes: 1