9

Korzystając z interfejsu Google Visualization API, używam google.visualization.data.group do tworzenia podfolderów na podstawie moich nieprzetworzonych danych. Moje nieprzetworzone dane używają triku {v: "US", f: "Stany Zjednoczone"}, aby wyświetlić coś innego niż wartość, ale kiedy używam funkcji agregacji, formatowanie jest eliminowane pozostawiając tylko część "US".Zachowaj formatowanie za pomocą grup według agregacji w interfejsie Google Visualization API

Czy istnieje sposób na zachowanie oryginalnego formatowania lub łatwy sposób dodania go ponownie do DataTables utworzonego przy użyciu agregacji grupowej?

dane próbki:

[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], 

Agregacja Funkcja:

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

Edit:

Na głębszego zastanowienia, to chyba niemożliwe do grupy z formatem, ponieważ nie ma gwarancji, że format każda wartość będzie spójna. Mając to na uwadze, prawdopodobnie lepiej (lub możliwe) napisać funkcję, która doda formaty do każdej kolumny moich danych. Więc pytanie brzmi: "Jak do cholery mam to zrobić?"

Wolałbym raczej nie tworzyć moich surowych danych jako niesformatowane wartości samodzielnie, a następnie dodatkowe tabele do wyszukiwania formatów dla każdej wartości. Wymagałoby to dodatkowych 2 tabel (jedna dla regionów, które ma 28 wierszy, jedna dla krajów, które ma ponad 240 wierszy), a następnie tworząc dwie funkcje, aby przejrzeć każdą wartość w zgrupowanej tabeli (która będzie miała ponad 30 lat danych, co oznacza tysiące linii) dodając wartości.

To wydaje się być naprawdę skomplikowanym rozwiązaniem.

Czy jest jakiś sposób, aby to zrobić z funkcjami modyfikatora? Czy mogę napisać funkcję zwracającą każdą wartość w tabeli jako obiekt w formacie {v: "US", f: "United States"}? Czy istnieje prosty sposób na napisanie formantu kolumn, który wyszuka odpowiednią wartość w mojej oryginalnej tabeli i przyjmie ten format? Co spowodowałoby najmniej bóle głowy zarówno dla mnie (kto musi to napisać), jak i dla użytkowników (którzy muszą go załadować)?

EDIT 2:

Wygląda na to, powinienem być w stanie stworzyć formatowania dla nowej tabeli za pomocą czegoś takiego:

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

Ale problem staje się, że skoro nie mam do czynienia z liczbą formatów, musiałbym utworzyć tabelę odnośników, która pobierze wartość, wyszuka ją w tabeli odnośników, a następnie zwróci odpowiedni format. Wygląda też na to, że mogę przechodzić przez całą tabelę, wiersz po wierszu, czyli tysiące linii.

Nie mogę sobie wyobrazić, że nie ma łatwego sposobu na zrobienie tego bez pętli z brutalną siłą i przypisywania wartości.

EDIT 3:

Więc próbowałem coś trudne. Zamiast ustawiać każdy wiersz jako wartość/format, utworzyłem część wartość/format jako ciąg, a następnie po grupowaniu użyłem eval() do oceny obiektów. To działało świetnie.Oto dane:

[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], 

tutaj jest nowy kod:

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

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

Kwestia jest taka, że ​​kiedy wyjście to do Google DataTable, pokazuje {V: 'AE', f: ' zjednoczone Emiraty Arabskie} pomimo faktu, że sprawdzanie wynik z eval właściwie daje mi:

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

Więc co robię źle tutaj?

Odpowiedz

1

Sam osobiście wpadłem na ten problem. Postanowiłem użyć modyfikatora, aby zmienić wartość na sformatowaną wartość przy użyciu oryginalnej tabeli dataTable, aby znaleźć sformatowane wartości. To nie jest strasznie wydajne, ale działa i komputery są szybkie.

Najpierw utworzyć funkcję odnośnika:

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; 
} 

następnie zadzwonić, że modyfikator, zmieniając oryginalnego połączenia grupowego:

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'}] 
); 

UPDATE: Wydaje się, że trzeba wartość i sformatowaną wartość zachowane. W moim przypadku wyświetlania wykresów kołowych nie dbam o zachowanie oryginalnej wartości. Sądzę, że to nie zadziała dla ciebie, ale zostawię tę odpowiedź tutaj dla innych, którzy mogą mieć prostszy przypadek jak mój.

Spędziłem kilka minut na tym i tutaj jest alternatywa, która skopiuje sformatowaną wartość, zachowując pierwotną wartość komórki.

Tworzenie funkcji kopiowania, która korzysta z funkcji wyszukiwania:

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); 
    } 

} 

Następnie w Twoim przypadku, nazywamy go raz dla każdej kolumny, którą chcesz skopiować.

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

Twoje źródłowy i docelowy kolumny są takie same, ale w niektórych przypadkach mogą one być różne.

Oczywiście, wszystko to stało się automatycznie.

4

OK, wymyśliłem to jedno (jak okropnie skomplikowane było).

Próbowałem nowego podejścia. Ponownie sformatowałem moje dane, a następnie utworzyłem funkcję zwracania wartości/formatu na podstawie dzielnika w tym ciągu. Więc moje dane wygląda teraz tak:

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

I wtedy to wykorzystać, aby uzyskać lokalizację dzielnik dla kolumny 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)); 
}; 

I wtedy skorzystać z tej funkcji, aby podzielić ciąg:

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 
    } 
     } 

Problem polega na tym, że definiuję kolumnę 1 moich danych jako "ciąg", ale firebug mówi mi, że obiekt zwrócony z funkcji splitFormat() jest obiektem (ponieważ jest to tablica, którą przypuszczam). Nawet jeśli ustawić oryginalną DataTable z AV: and F składnik, nie chcą przyjąć zwrócony wartość obiektu tablicy, jak FireBug daje mi następujące jakże cenne rady:

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

Kwestia jest to, że można zdefiniować DataTable za pomocą składni {v:, f:}, nie można przywrócić tej składni z powrotem do tabeli, ponieważ wartość dla tej kolumny jest ustawiona jako ciąg. Zamiast tego użyłem „setFormattedValue” właściwość DataTable, aby rozwiązać problem:

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); 
    }; 

To właściwie dał mi odpowiednie wartości dla obu, chociaż jest nieco intensywny dla dużych zbiorów danych. Jeśli ktoś wie o łatwiejszym sposobie, aby to zrobić, byłbym bardziej niż szczęśliwy, aby to usłyszeć.

Powiązane problemy