'what is the equivalent group code for nest and group functions in D3 V6
I am absolute new to both JavaScript and D3. I have problem to convert below D3 codes from version 3 to 6 .
data:
d2.csv:
city,type,price,id
a,c,10,1
a,c,15,2
a,d,30,3
a,d,40,4
a,e,5,5
a,e,10,6
a,e,7,7
b,c,15,8
b,c,20,9
b,d,9,10
b,d,4,11
b,e,12,12
b,e,15,13
D3 V3 code:
data = d3.csv('./data/d2.csv', function (data) {
var nestedData = d3.nest()
.key(function (d) { return d.city; }).sortKeys(d3.descending)
.key(function (d) { return d.type; }).sortKeys(d3.ascending)
.sortValues(function (a, b) { return +b.price - +a.price; })
.entries(data);
console.log(nestedData);
})
please help me with version 6
Solution 1:[1]
You can use the logic of the little helper function in this answer to convert the nested Map
returned from d3.group
back into an Object
with the format you expect per d3.nest
. This should work for any level of nesting.
To accommodate the sorting logic, use d3.ascending
and d3.descending
over the array of objects you get from your CSV before you call d3.group
.
Working example:
const csv = `city,type,price,id
a,c,10,1
a,c,15,2
a,d,30,3
a,d,40,4
a,e,5,5
a,e,10,6
a,e,7,7
b,c,15,8
b,c,20,9
b,d,9,10
b,d,4,11
b,e,12,12
b,e,15,13`;
// helper function to convert nested Map to {key: x, values: []} format
const mapToObject = (map = new Map) => Array.from(
map.entries(),
([k, v]) => ({
"key": k,
"values": v instanceof Map ? mapToObject(v) : v
})
);
// get the data and apply the sorting logic
const data = d3.csvParse(csv)
.sort((a, b) => d3.descending(a.city, b.city)
|| d3.ascending(a.type, b.type)
|| d3.descending(+a.price, +b.price));
// call the helper function with output of d3.group
const nestedData = mapToObject(
d3.group(
data,
d => d.city,
d => d.type
)
);
// same result as your d3.nest example
console.log(nestedData);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>
Solution 2:[2]
Apparently, there is no direct equivalent for d3.nest
in V6. I tried d3.group
/ d3.groups
/ d3.rollup
but did not get exactly the same result...
Instead, you can use the following code:
d3.csv('./data/d2.csv', function (data) {
const nestedData = data
.sort((a, b) => {
if (a.city > b.city) return -1;
if (a.city < b.city) return 1;
if(a.type > b.type) return 1;
if(a.type < b.type) return -1;
return b.price - a.price;
})
.reduce((arr, item) => {
const cityObj = arr.find(({key}) => key === item.city);
if (!cityObj) {
arr.push({key: item.city, values: [{key: item.type, values: [item]}]});
return arr;
}
const typeObj = cityObj.values.find(({key}) => key === item.type);
if (!typeObj) {
cityObj.values.push({key: item.type, values: [item]});
return arr;
}
typeObj.values.push(item);
return arr;
}, []);
console.log(nestedData);
});
Here is my fiddle with a tested code.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Robin Mackenzie |
Solution 2 | Michael Rovinsky |