[Update]: I've removed most of the layout and lodash (failed code) from before because the JSON data format has changed.
I'm trying to group a data set in preparation for aggregating totals. Here is the incoming JSON layout. I need to group by country, then by brand:
[
{
$id: "1",
countryCode: "HT",
brand: "CO",
roomNights: 12,
hotelSpend: 2000
},
{
$id: "2",
countryCode: "PK",
brand: "HH",
roomNights: 201,
hotelSpend: 10000
},
{
$id: "3",
countryCode: "RO",
brand: "CO",
roomNights: 34,
hotelSpend: 5000
},
{
$id: "4",
countryCode: "US",
brand: "ES",
roomNights: 120,
hotelSpend: 56000
},
{
$id: "5",
countryCode: "PK",
brand: "HH",
roomNights: 145,
hotelSpend: 33000
}
]
The data needs to be transformed into this format:
['Brand','HT' , 'PK' , 'US' , 'RO', 'Avg Rm', 'Avg Spend']
['HH' ,'0/0' ,'201/10000', '0/0' , '0/0' , 201, 10000],
['CO' ,'12/2000','0/0', , '0/0' , '34/5000', 23 , 3500],
['ES' , '0/0' ,'0/0' , '120/50000' , '0/0' , 120, 50000]
The roomNights and hotelSpend will be totalled per brand & country and the average of each will need to be calculated fields at the end.
Thanks!
Let's first define a mean
function and add it to _
:
_.mixin({
mean: function(ds) {
return _(ds).foldr(function(a, b) { return a + b; }, 0) / ds.length;
}
});
Let's define functions for selecting the rows and columns:
var row = function(d) { return d.brand; };
var col = function(d) { return d.countryCode; };
aggr
function takes a sub-list of our data and aggregates its values into one value (which here is a string representation of a rational number):
var aggr = function(ds) {
var val = _(ds).foldr(function(a, b) {
return {
roomNights: a.roomNights + b.roomNights,
hotelSpend: a.hotelSpend + b.hotelSpend
};
}, {roomNights: 0, hotelSpend: 0});
return val.roomNights + "/" + val.hotelSpend;
};
Our rows and columns labels:
rows = _.chain(data).map(row).unique().value();
columns = _.chain(data).map(col).unique().value();
The pivot:
[["Brand/Country"].concat(columns).concat(["Avg Rm", "Avg Spend"])] // header row
.concat(_(rows).map(function(r){
// data in this row
rdata = _(data).filter(function(d) { return row(d) == r; });
return [r].concat(_(columns).map(function(c){
return aggr(_(rdata).filter(function(d) {return col(d) == c; }));
}))
// the last two columns in each row
.concat([
_.chain(rdata).map(function(d) { return d.roomNights; }).mean().value(),
_.chain(rdata).map(function(d) { return d.hotelSpend; }).mean().value()
]);
}));
You can control the order or filter the result by specific countryCode
or brand
by modifying the rows
and columns
arrays, similar to spreadsheets.
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.