使用javascript将“长”数据转换为“宽”数组

时间:2015-01-13 19:03:44

标签: javascript r casting google-visualization

在R中,有一种非常方便的方式来改变“长”。将数据放入' wide',使用dcast包中的{reshape2}应用函数(如计算出现次数)。我想在javascript中使用类似的转换。 R示例(带sample data):

library(reshape2)
data.long = read.table("so_question2.csv", sep = "\t")

head(data.long)
# This is how a first few rows of the original data look like:
#    dpt    sem
# 15 Dpt.4  2014.1
# 16 Dpt.4  2014.1
# 17 Dpt.4  2014.1
# 18 Dpt.4  2014.1
# 19 Dpt.4  2014.1
# 20 Dpt.4  2014.1

data.wide = dcast(data, sem ~ dpt, length)

head(data.wide)
# This is how it looks like after the transformation; there are counts in columns now
#   sem        Dpt.1 Dpt.2 Dpt.3 Dpt.4
# 1 2012.1     0     0     0     8
# 2 2012.2     3     6     0    21
# 3 2013.1     3     4     0    29
# 4 2013.2     5     1     2    39
# 5 2014.1     5     3     7    39

为什么我需要这个:我正在学习使用Google Charts,并且希望能够在电子表格中importing them之后转换数据。我知道我可以在电子表格中进行转换;但是使用大量公式使电子表格混乱会非常不方便。我更希望每个图表在自己的脚本中进行自己的转换。

1 个答案:

答案 0 :(得分:1)

我有同样的问题!这是一个方便的功能。

// helper function
function addIfMissing(array, value) {
    var found = false;
    for(var i = 0; i < array.length; i++)
        if(array[i] === value)
            return array;
    array.push(value);
    return array;
}

function restructure(input) {
    var output = [], headerX = [], headerY = [], xCoor, yCoor;

    // first create non-repeating headers
    headerX.push(input[0][0]);
    headerY.push(input[0][0]);
    for(var i = 1; i < input.length; i++)
        headerX = addIfMissing(headerX, input[i][0]), headerY = addIfMissing(headerY, input[i][1]);

    // put headers into output array
    for(var i = 0; i < headerX.length; i++)
        output.push([headerX[i]]);
    output[0] = headerY;

    // find correct headers on both axes and input data
    for(var i = 1; i < input.length; i++) {
        for(var k = 1; k < headerX.length; k++)
            if(output[k][0] == input[i][0])
                xCoor = k;
        for(var j = 1; j < headerY.length; j++)
            if(output[0][j] == input[i][1])
                yCoor = j;
        output[xCoor][yCoor] = input[i][2];
    }

    return output;
}

我用它测试了它:

var input = [
    ['Season', 'Type', 'Number'],
    ['Winter', 'Sales', 1000],
    ['Winter', 'Expenses', 400],
    ['Winter', 'Profit', 200],
    ['Spring', 'Sales', 1170],
    ['Spring', 'Expenses', 460],
    ['Spring', 'Profit', 250],
    ['Summer', 'Sales', 660],
    ['Summer', 'Expenses', 1120],
    ['Summer', 'Profit', 300],
    ['Fall', 'Sales', 1030],
    ['Fall', 'Expenses', 540],
    ['Fall', 'Profit', 350]
];

var desiredOutput = [
    ['Season', 'Sales', 'Expenses', 'Profit'],
    ['Winter', 1000, 400, 200],
    ['Spring', 1170, 460, 250],
    ['Summer', 660, 1120, 300],
    ['Fall', 1030, 540, 350]
];

var output = restructure(input);

if (JSON.stringify(output) == JSON.stringify(desiredOutput)) 
    alert("Pass");

Test example JSFiddle

And example of how I implemented it with google charts