2013-11-03 25 views
6

Considerate i seguenti dati tabulari (solo un esempio):Come ruotare una tabella con 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 

noti che ogni combinazione di valori distinti per colonne A, B, C e D avviene esattamente una volta in questa tabella. Quindi, si può pensare a questo sottoinsieme di colonne come alle "colonne chiave" e alle colonne rimanenti come alle "colonne valore".

Diciamo che questo dato è in qualche file di data.csv, e che leggiamo questo file con d3.csv, nella discussione di callback data, in questo modo:

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

Sto cercando una vantaggiosa d3.js manipolazione per trasformare data in modo che la colonna C sia "ruotata". Con questo intendo che le colonne "valore" della tabella trasformata sono quelle ottenute "incrociando" i valori della colonna C con le colonne "valore" originali, x, e z. In altre parole, in formato CSV, la tabella trasformato sarebbe simile a questa:

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 

Nel caso in cui non c'è un modo semplice per farlo, una variante più semplice (ma sempre utile) sarebbe quella di fare una trasformazione simile dopo la prima scartando tutte tranne una delle colonne "valore". Ad esempio, dopo aver eliminato le x e y colonne, facendo perno sulla colonna C produrrebbe (in formato 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 

La semplificazione consiste nel fatto che ora la colonna valore originale (z) può essere semplicemente sostituita da un insieme di colonne denominate in base ai valori (c0 e c1 in questo caso) nella colonna ruotata (C).

risposta

8

Stai cercando 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, ' ')); 
}); 

Il risultato in nestedData sarebbe il seguente formato:

[ 
    { 
    "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" 
    } 
] 

Demo Guardate script.js e l'uscita sul console.

+0

scusate, ci deve essere stato un equivoco da qualche parte, perché questo non è nemmeno lontanamente vicino a quello che sto cercando ... – kjo

+0

Le mie scuse. L'errore stava trascurando la forma esatta in cui avevi bisogno dei dati, avevo presunto che volevi semplicemente un 'GROUP BY' sulla colonna' C'. Ho aggiornato la risposta con la soluzione corretta: http://plnkr.co/edit/Pr1Fnak6y3suSaY4j9pt?p=preview –

+0

+1 molto interessante! Grazie! – kjo