10

GoogleのVisualizationAPIを使用して、google.visualization.data.groupを使用して、生データに基づいてサブテーブルを作成します。私の生データは{v: "US"、f: "United States"}のトリックを使用して値以外のものを表示しますが、集計関数を使用すると、フォーマットが削除され、「US」部分のみが残ります。

元のフォーマットを保持する方法、またはグループ集計を使用して作成されたDataTableに元のフォーマットを追加する簡単な方法はありますか?

サンプルデータ:

[2010, {v:"MA", f:"Morocco"}, {v:"002", f:"Africa"}, {v:"002", f:"Northern Africa"}, 21.12724],
[2010, {v:"AW", f:"Aruba"}, {v:"019", f:"Americas  "}, {v:"019", f:"Caribbean"}, 0.98],
[2010, {v:"AF", f:"Afghanistan"}, {v:"142", f:"Asia"}, {v:"142", f:"Southern Asia"}, 0.9861],
[2010, {v:"AO", f:"Angola"}, {v:"002", f:"Africa"}, {v:"002", f:"Middle Africa"}, 5.11774],

集計関数:

var countryData = google.visualization.data.group(
  rawData, 
  [0, 1], 
  [{'column': 4, 'aggregation': google.visualization.data.sum, 'type': 'number'}]
);

編集:

さらに考えてみると、各値の形式が一貫しているという保証がないため、形式でグループ化することはおそらく不可能です。そのことを念頭に置いて、データの各列に形式を追加する関数を作成する方がおそらく良い(または可能である)でしょう。したがって、質問は「どうやってそれを行うのか」ということになります。

生データをフォーマットされていない値だけで作成したり、各値のフォーマットを検索するための追加のテーブルを作成したりするのは、実際には避けたいと思います。これには、追加の2つのテーブル(1つは28行のリージョン用、もう1つは240行を超える国用)が必要です。次に、グループ化されたテーブル(30年以上のデータが含まれる)の各値を調べる2つの関数を作成します。数千行を意味します)値を追加します。

それは本当に複雑な解決策のようです。

修飾子関数を使用してこれを行う方法はありますか?テーブル内の各値を{v: "US"、f: "United States"}形式のオブジェクトとして返す関数を記述できますか?または、元のテーブルで適切な値を検索してその形式を採用する列フォーマッターを作成する簡単な方法はありますか?私(それを書かなければならない人)とユーザー(それをロードしなければならない人)の両方にとって、どちらが最も頭痛の種になるでしょうか?

編集2:

次のようなものを使用して、新しいテーブルのフォーマッタを作成できるはずです。

function (dt, row) {
    return {
        v: (dt.getValue(row, 1) / 1000000),
        f: (dt.getValue(row, 1) / 1000000) + 'M'
    }
}

しかし、問題は、数値形式を扱っていないため、値を取得するある種のルックアップテーブルを作成し、それをルックアップテーブルで検索してから、適切な形式を返す必要があるということです。また、テーブル全体を1行ずつループする必要があるように見えます。これは数千行です。

力ずくのループと値の割り当てなしにこれを行う簡単な方法がないことは想像できません。

編集3:

だから私はトリッキーなことを試みました。各行を値/フォーマットとして設定するのではなく、値/フォーマット部分を文字列として作成し、グループ化した後、eval()を使用してオブジェクトを評価しました。これはうまくいきました。データは次のとおりです。

[2010, "{v: 'MA', f: 'Morocco'}", 21.13],
[2010, "{v: 'AW', f: 'Aruba'}", 0.98],
[2010, "{v: 'AF', f: 'Afghanistan'}", 0.99],
[2010, "{v: 'AO', f: 'Angola'}", 5.12],

新しいコードは次のとおりです。

  var countryCount = countryData.getColumnRange(0).count;

  for (var i = 0; i <= countryCount; i++) {
    countryData.setValue(i, 1, eval('(' + countryData.getValue(i,1) + ')'));
  };

問題は、これをGoogle DataTableに出力すると、evalで結果を適切にチェックすると次のようになるにもかかわらず、{v:'AE'、f:'アラブ首長国連邦'}と表示されることです。

>>> eval('(' + countryData.getValue(i,1) + ')')
Object v="AE" f="United Arab Emirates"

それで、私はここで何を間違っているのですか?

4

2 に答える 2

4

さて、私はこれを理解しました(それがどれほど厄介に複雑であったか)。

新しいアプローチを試しました。データを再フォーマットしてから、その文字列内の仕切りに基づいて値/形式を返す関数を作成しました。したがって、私のデータは次のようになります。

[2010, "'MA'|'Morocco'", 21.13],
[2010, "'AW'|'Aruba'", 0.98],
[2010, "'AF'|'Afghanistan'", 0.99],
[2010, "'AO'|'Angola'", 5.12],

次に、これを使用して、列1の仕切りの位置を取得します。

var countryCount = countryData.getNumberOfRows();

for (var i = 0; i <= countryCount; i++) {
  var stringToSplit = countryData.getValue(i,1);
  var dividerLocation = stringToSplit.indexOf("|");
  alert("Divider: " + dividerLocation + ", String: " + stringToSplit);
  countryData.setValue(i, 1, splitFormat(dividerLocation, stringToSplit));
};

次に、この関数を使用して文字列を分割します。

  function splitFormat(dividerLocation, stringToSplit) {
    // alert("entered splitFormat Function");
    var stringValue = "";
    var formatValue = "";
    stringValue = stringToSplit.substring(0, dividerLocation);
    formatValue = stringToSplit.substring(dividerLocation + 1)
    alert("v: " + stringValue + ", f: " + formatValue);
    return {
      v: stringValue,
      f: formatValue
    }
      }

問題は、データの列1を「文字列」として定義していることですが、firebugは、splitFormat()関数から返されるオブジェクトがオブジェクトであることを通知しています(これは、私が推測する配列であるため)。元のデータテーブルをav:およびf:コンポーネントで設定したとしても、FireBugが次の非常に役立つアドバイスを提供するため、返された配列オブジェクト値を受け入れたくありません。

"Error: Type mismatch. Value [object Object] does not match type string in column index 1 (table.I.js,137)"

問題は、{v:、f:}構文を使用してDataTableを定義できますが、その列の値が文字列として設定されているため、その構文をテーブルに戻すことができないことです。代わりに、DataTableの「setFormattedValue」プロパティを使用して問題を修正しました。

  function drawVisualization() {
    var countryTable = new google.visualization.Table(document.getElementById('table'));

    var countryCount = countryData.getNumberOfRows() - 1;

    for (var i = 0; i <= countryCount; i++) {
      var stringToSplit = countryData.getValue(i,1);
      var dividerLocation = stringToSplit.indexOf("|");
      var stringValue = stringToSplit.substring(0, dividerLocation);
      var stringFormat = stringToSplit.substring(dividerLocation + 1);
      countryData.setValue(i, 1, stringValue);
      countryData.setFormattedValue(i, 1, stringFormat);
    };

これにより、大規模なデータセットでは少し集中的になりますが、両方に適切な値が適切に与えられました。誰かがこれを行うためのより簡単な方法を知っているなら、私はそれを聞いてとても幸せです。

于 2013-01-07T02:14:20.390 に答える
2

私は自分でこの問題に遭遇しました。修飾子を使用して、元のdataTableを使用して値をフォーマットされた値に変更し、フォーマットされた値を見つけることにしました。これはそれほど効率的ではありませんが、機能し、コンピューターは高速です。

まず、ルックアップ関数を作成します。

function getFormatForValue(dataTable, column, value) {

    // we need to spin through column in the dataTable looking
    // for the matching value and then return the formatted value
    var rowcount = dataTable.getNumberOfRows();
    for (var i=0; i<rowcount; i++) {
        if (dataTable.getValue(i, column) === value) {

            // we found it, this will look much better
            return dataTable.getFormattedValue(i, column);    
        }
    }

    // better than nothing
    return value;
}

次に、それを修飾子で呼び出し、元のグループ呼び出しを変更します。

var countryData = google.visualization.data.group(
    rawData, 
    [
     {
      'column': 0,
      'modifier': function(value) { return getFormatForValue(rawData, 0, value); },
      'type': 'string'
     },
     {
      'column': 1,
      'modifier': function(value) { return getFormatForValue(rawData, 1, value); },
      'type': 'string'
     }
    ], 
    [{'column': 4, 'aggregation': google.visualization.data.sum, 'type': 'number'}]
);

更新:値とフォーマットされた値を保持する必要があるようです。円グラフを表示する場合、元の値を保持する必要はありません。これはあなたにはうまくいかないと思いますが、私のようなもっと単純なケースを持っているかもしれない他の人のために、この答えをここに残しておきます。

これにさらに数分を費やしました。これは、元のセル値を保持したまま、フォーマットされた値をコピーする代替手段です。

ルックアップ関数を使用するコピー関数を作成します。

function copyFormattedValues(oldDataTable, oldColumn, newDataTable, newColumn) {

    var rowcount = newDataTable.getNumberOfRows();
    for (var i=0; i<rowcount; i++) {
        var value = newDataTable.getValue(i, newColumn);
        var formatted = getFormatForValue(oldDataTable, oldColumn, value);
        newDataTable.setFormattedValue(i, newColumn, formatted);
    }

 }

次に、あなたの場合、コピーしたい列ごとに1回呼び出します。

copyFormattedValues(rawData, 0, countryData, 0);
copyFormattedValues(rawData, 1, countryData, 1);

ソース列と宛先列は同じですが、異なる場合があります。

もちろん、理想的には、これらすべてが自動的に行われるはずです。

于 2015-02-11T16:49:06.820 に答える