JavaScript
二次元配列
クロス集計
More than 3 years have passed since last update.

簡単なクロス集計を実現するためのJavaScriptコードです。

縦軸・横軸・集計対象を指定すれば二次元配列で集計結果を確認できます。

随分探したのですが、ちょうどいいのがなかったので書き起こしました。


変換イメージ


元データ

shop
staff
month
price

新宿
yamada
5月
100

新宿
yamada
6月
200

渋谷
tanaka
5月
300

渋谷
sato
6月
400


クロス集計の結果

shop
staff
5月
6月

新宿
山田
100
200

渋谷
田中
300
0

渋谷
佐藤
0
400


使い方


元データの準備


  • src_dataに2次元配列でデータを格納

  • src_data_fieldsにフィールド名を指定


クロス集計の条件


  • var pivot_row_fieldに横軸(表頭)を1つだけ指定

  • var pivot_val_fieldに集計対象を1つだけ指定

  • var pivot_col_fieldsに縦軸(表側)を指定 ※カンマ区切りで複数指定可


コード


pivot.js


// 対象データを二次元配列で定義
var src_data_fields = [ "shop", "staff", "month", "sales" ];
var src_data = [
[ "新宿", "山田", "5月", "100" ],
[ "新宿", "山田", "6月", "200" ],
[ "渋谷", "田中", "5月", "300" ],
[ "渋谷", "佐藤", "6月", "400" ]
];

// 設定条件
var pivot_row_field = "month"; // 横軸(表頭) ※1つだけ指定
var pivot_val_field = "sales"; // 集計対象  ※1つだけ指定
var pivot_col_fields = "shop,staff";// 縦軸(表側) ※カンマ区切りで複数指定可

// 処理用の変数
var agg_vals = {};
var pivot_row_vals_hash = {};

// 処理開始
var pivot_col_fields_array = pivot_col_fields.split(",");

for( var i = 0; i < src_data.length; i++ ){

// 処理しやすいようにレコードを連想配列化
var recs = {};
for( var j = 0; j < src_data_fields.length; j++ ){
recs[src_data_fields[j]] = src_data[i][j];
}

// 集計値の確認
var agg_val = parseInt( recs[pivot_val_field] );
if( ! agg_val ){
continue;
}

// 集計の縦軸
var key = "";
for( var j = 0; j < pivot_col_fields_array.length; j++ ){
key += "\t" + recs[ pivot_col_fields_array[j] ];
}
key = key.replace( /^\s+/, "" );

// 集計の横軸
var pivot = recs[pivot_row_field];
pivot_row_vals_hash[pivot] = 1;

// 縦軸・横軸の二次元で集計
if( typeof agg_vals[key] == "undefined" ){
agg_vals[key] = {};
}
if( typeof agg_vals[key][pivot] == "undefined" ){
agg_vals[key][pivot] = 0;
}
agg_vals[key][pivot] += agg_val;

}

// 横軸の値をソート ※ブラウザによってkeysが使えなのでforで回す
var pivot_row_vals = [];
for( var pivot_row_val in pivot_row_vals_hash ){
pivot_row_vals.push( pivot_row_val );
}

// 出力用配列の準備
var result = [];
var out_fields = [];
out_fields = out_fields.concat(pivot_col_fields_array);
out_fields = out_fields.concat(pivot_row_vals);
result.push( out_fields );

// 出力用データ
for( var agg_key in agg_vals ){
var out_row = [];
out_row = out_row.concat( agg_key.split("\t") )
for( var j = 0; j < pivot_row_vals.length; j++ ){
var cell_val = agg_vals[agg_key][pivot_row_vals[j]] || 0;
out_row.push(cell_val);
}
result.push(out_row);
}

console.log( JSON.stringify(result,null,2) );