2013-11-03 95 views
6

考慮以下表格數據(只是一個例子):如何使用d3.js來旋轉表格?

A,B,C,D,x,y,z 
a0,b0,c0,d0,0.007,0.710,0.990 
a0,b0,c0,d1,0.283,0.040,1.027 
a0,b0,c1,d0,0.017,0.688,2.840 
a0,b0,c1,d1,0.167,0.132,2.471 
a0,b1,c0,d0,0.041,0.851,1.078 
a0,b1,c0,d1,0.235,1.027,1.027 
a0,b1,c1,d0,0.037,0.934,2.282 
a0,b1,c1,d1,0.023,1.049,2.826 
a1,b0,c0,d0,0.912,0.425,1.055 
a1,b0,c0,d1,0.329,0.932,0.836 
a1,b0,c1,d0,0.481,0.681,0.997 
a1,b0,c1,d1,0.782,0.595,2.294 
a1,b1,c0,d0,0.264,0.918,0.857 
a1,b1,c0,d1,0.053,1.001,0.920 
a1,b1,c1,d0,1.161,1.090,1.470 
a1,b1,c1,d1,0.130,0.992,2.121 

注意,對於CAB,不同的值的每一種組合,和D在此表中正好出現一次。因此,可以將此列的子集看作「關鍵列」,將其餘列視爲「值列」。

比方說,這個數據是在一些文件data.csv,而我們閱讀與d3.csv該文件,進入回調參數data,就像這樣:

d3.csv('data.csv', function (error, data) { 
    ... 
}); 

我正在尋找一個方便d3.js操縱轉換data以便C列是「pivoted」。這意味着轉換表的「值」列是通過將C列的值與原始「值」列x,yz「交叉」而獲得的列。換句話說,CSV格式,轉換後的表是這樣的:

A,B,D,x_c0,x_c1,y_c0,y_c1,z_c0,z_c1 
a0,b0,d0,0.007,0.017,0.710,0.688,0.990,2.840 
a0,b0,d1,0.283,0.167,0.040,0.132,1.027,2.471 
a0,b1,d0,0.041,0.037,0.851,0.934,1.078,2.282 
a0,b1,d1,0.235,0.023,1.027,1.049,1.027,2.826 
a1,b0,d0,0.912,0.481,0.425,0.681,1.055,0.997 
a1,b0,d1,0.329,0.782,0.932,0.595,0.836,2.294 
a1,b1,d0,0.264,1.161,0.918,1.090,0.857,1.470 
a1,b1,d1,0.053,0.130,1.001,0.992,0.920,2.121 

萬一有沒有簡單的方法來做到這一點,一個簡單的(但仍然有用)的變體將是第一後做類似的轉型丟棄除「價值」欄之外的所有欄。例如,丟棄xy列之後,樞轉C柱將產生(以CSV格式):

A,B,D,c0,c1 
a0,b0,d0,0.990,2.840 
a0,b0,d1,1.027,2.471 
a0,b1,d0,1.078,2.282 
a0,b1,d1,1.027,2.826 
a1,b0,d0,1.055,0.997 
a1,b0,d1,0.836,2.294 
a1,b1,d0,0.857,1.470 
a1,b1,d1,0.920,2.121 

的簡化在於,現在原始值柱(z)可以由一組簡單地更換(c0c1,在這種情況下)在列表中已被透視的列中(C)。

回答

8

您正在尋找d3.nest

d3.csv('data.csv', function (data) { 
    var nester = d3.nest() 
    .key(function (d) { return d.A; }) 
    .key(function (d) { return d.B; }) 
    .key(function (d) { return d.D; }) 
    .rollup(function (values) { 
     var sortedValues = values.sort(function (x, y) { 
     return x.C < y.C ? -1 : x.C > y.C ? 1 : 0; 
     }); 
     var mkKey = function (c, name, v) { 
     return { 
      name: 'C_' + c + '_' + name, 
      value: v 
     }; 
     } 

     var pivotedX = sortedValues.map(function (d) { return mkKey(d.C, 'x', d.x); }), 
      pivotedY = sortedValues.map(function (d) { return mkKey(d.C, 'y', d.y); }), 
      pivotedZ = sortedValues.map(function (d) { return mkKey(d.C, 'z', d.z); }); 

     return Array.prototype.concat.apply([], [pivotedX, pivotedY, pivotedZ]); 
    }); 

    var nestedData = nester.entries(data); 
    var pivotedData = []; 

    nestedData.forEach(function (kv1) { 
    var a = kv1.key; 
    kv1.values.forEach(function (kv2) { 
     var b = kv2.key; 
     kv2.values.forEach(function (kv3) { 
     var d = kv3.key; 
     var obj = { 
      A: a, 
      B: b, 
      D: d 
     }; 

     kv3.values.forEach(function (d){ 
      obj[d.name] = d.value; 
     }) 
     pivotedData.push(obj); 
     }) 
    }) 
    }) 
    console.log(JSON.stringify(pivotedData, null, ' ')); 
}); 

nestedData其結果將是以下形式:

[ 
    { 
    "A": "a0", 
    "B": "b0", 
    "D": "d0", 
    "C_c0_x": "0.007", 
    "C_c1_x": "0.017", 
    "C_c0_y": "0.710", 
    "C_c1_y": "0.688", 
    "C_c0_z": "0.990", 
    "C_c1_z": "2.840" 
    }, 
    ..., 
    { 
    "A": "a1", 
    "B": "b1", 
    "D": "d1", 
    "C_c0_x": "0.053", 
    "C_c1_x": "0.130", 
    "C_c0_y": "1.001", 
    "C_c1_y": "0.992", 
    "C_c0_z": "0.920", 
    "C_c1_z": "2.121" 
    } 
] 

Demoscript.js,並在console輸出。

+0

對不起,一定有某種誤解,因爲這甚至不是很接近我所尋找的... – kjo

+0

我的歉意。這個錯誤忽略了你需要數據的確切形式,我假設你只想在列「C」上使用「GROUP BY」。我已經用正確的解決方案更新了答案:http://plnkr.co/edit/Pr1Fnak6y3suSaY4j9pt?p=preview –

+0

+1非常酷!謝謝! – kjo