Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

JavaScriptでクロス集計

More than 5 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) );

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away