9

Sử dụng API trực quan hóa của Google, tôi sử dụng google.visualization.data.group để tạo các bảng phụ dựa trên dữ liệu thô của tôi. Dữ liệu thô của tôi sử dụng mẹo {v: "US", f: "Hoa Kỳ"} để hiển thị thông tin khác ngoài giá trị, nhưng khi tôi sử dụng hàm tổng hợp, định dạng được loại bỏ chỉ để lại phần "Hoa Kỳ".Giữ lại định dạng bằng cách sử dụng nhóm theo tổng hợp trong API hình ảnh hóa của Google

Có cách nào để giữ nguyên định dạng ban đầu hay cách dễ dàng để thêm lại dữ liệu trên DataTables được tạo bằng cách sử dụng tổng hợp nhóm không?

dữ liệu mẫu:

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

Aggregation Chức năng:

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

Edit:

On suy nghĩ xa hơn, nó có thể là bất khả thi vào nhóm với định dạng vì không có gì đảm bảo rằng các định dạng cho mỗi giá trị sẽ nhất quán. Với ý nghĩ đó, có lẽ tốt hơn (hoặc chỉ có thể) để viết một hàm sẽ thêm các định dạng vào mỗi cột dữ liệu của tôi. Vì vậy, câu hỏi trở thành, "Làm thế nào tôi có thể làm điều đó?"

Tôi thực sự không muốn tạo dữ liệu thô của mình dưới dạng giá trị chưa định dạng một mình và sau đó là các bảng bổ sung để tìm kiếm định dạng cho từng giá trị. Điều đó sẽ yêu cầu thêm 2 bảng (một cho các vùng là 28 hàng, một cho các quốc gia có trên 240 hàng) và sau đó tạo hai hàm để xem xét từng giá trị trong bảng được nhóm (sẽ có 30 năm dữ liệu, có nghĩa là hàng ngàn dòng) thêm các giá trị.

Điều đó có vẻ giống như một giải pháp thực sự phức tạp.

Có cách nào để thực hiện điều này với các chức năng bổ trợ không? Tôi có thể viết một hàm trả về mỗi giá trị trong bảng dưới dạng đối tượng được định dạng {v: "US", f: "Hoa Kỳ"} không? Hoặc là có một cách dễ dàng để viết một định dạng cột sẽ tìm kiếm giá trị thích hợp trong bảng ban đầu của tôi và áp dụng định dạng đó? Mà sẽ gây ra đau đầu ít nhất cho cả tôi (người đã viết nó), và cho người sử dụng (những người phải tải nó)?

EDIT 2:

Dường như tôi sẽ có thể tạo ra một định dạng cho bảng mới sử dụng một cái gì đó như thế này:

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

Nhưng vấn đề trở nên rằng kể từ khi tôi không làm việc với số định dạng, tôi sẽ phải tạo một số loại bảng tra cứu sẽ lấy giá trị, tra cứu nó trong bảng tra cứu, và sau đó trả về định dạng thích hợp. Nó cũng có vẻ như tôi có thể phải lặp qua toàn bộ bảng, hàng theo hàng, đó là hàng ngàn dòng.

Tôi không thể tưởng tượng rằng không có cách dễ dàng để làm điều này mà không có một số vòng lặp brute force và gán giá trị.

CHỈNH SỬA 3:

Vì vậy, tôi đã thử một số điều khó khăn. Thay vì thiết lập mỗi hàng dưới dạng giá trị/định dạng, tôi đã tạo phần giá trị/định dạng dưới dạng một chuỗi và sau đó sau khi nhóm eval() được sử dụng để đánh giá các đối tượng. Điều này làm việc tuyệt vời.Đây là dữ liệu:

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

đây là đoạn code mới:

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

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

Vấn đề là khi tôi ra này vào một DataTable Google, nó cho thấy {v: 'AE', f: ' Các Tiểu vương quốc Ả Rập Thống nhất '} mặc dù thực tế rằng việc kiểm tra kết quả với eval đúng cho tôi:

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

Vì vậy, tôi đang làm gì sai ở đây?

Trả lời

1

Tôi chỉ tự mình gặp sự cố này. Tôi quyết định sử dụng công cụ sửa đổi để thay đổi giá trị thành giá trị được định dạng bằng cách sử dụng bảng dữ liệu gốc để tìm các giá trị được định dạng. Đây không phải là hiệu quả khủng khiếp, nhưng nó hoạt động và máy tính nhanh.

Đầu tiên tạo một hàm lookup:

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

Sau đó, gọi đó là trong sửa đổi, thay đổi nhóm gọi ban đầu của bạn:

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

Cập nhật: Có vẻ như bạn cần giá trị và giá trị được định dạng bảo quản. Trong trường hợp hiển thị biểu đồ hình tròn của tôi, tôi không quan tâm đến việc giữ nguyên giá trị ban đầu. Tôi đoán điều này sẽ không hiệu quả với bạn, nhưng tôi sẽ để lại câu trả lời ở đây cho những người khác có thể có một trường hợp đơn giản như tôi.

Tôi đã dành thêm vài phút cho điều này và đây là một thay thế sẽ sao chép giá trị được định dạng trong khi vẫn giữ giá trị ô ban đầu.

Tạo một chức năng sao chép có sử dụng chức năng tra cứu:

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

} 

Sau đó, trong trường hợp của bạn, hãy gọi nó một lần cho mỗi cột bạn muốn sao chép.

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

Cột nguồn và đích của bạn giống nhau nhưng trong một số trường hợp, chúng có thể khác nhau.

Tất nhiên, lý tưởng nhất là điều này sẽ tự động xảy ra.

4

Được rồi, tôi đã tìm ra điều này (mức độ phức tạp của nó).

Tôi đã thử một cách tiếp cận mới. Tôi đã định dạng lại dữ liệu của mình và sau đó tạo một hàm để trả về một giá trị/định dạng dựa trên một dải phân cách trong chuỗi đó. Vì vậy, dữ liệu của tôi bây giờ trông như thế này:

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

sau đó tôi sử dụng để có được vị trí chia cho cột 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)); 
}; 

Và sau đó tôi sử dụng chức năng này để chia chuỗi:

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

Vấn đề là tôi đang xác định cột 1 của dữ liệu là 'chuỗi', nhưng firebug cho tôi biết rằng đối tượng được trả về từ hàm splitFormat() là một đối tượng (vì nó là mảng mà tôi giả sử). Thậm chí nếu tôi đặt DataTable ban đầu với av: và f: thành phần, nó không muốn chấp nhận một giá trị đối tượng mảng được trả về, như Firebug mang lại cho tôi những lời khuyên oh-so-hữu ích sau đây:

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

Vấn đề này là trong khi bạn có thể định nghĩa một DataTable bằng cách sử dụng cú pháp {v:, f:}, bạn không thể trả về cú pháp đó trở lại bảng vì giá trị cho cột đó được đặt là chuỗi. Thay vào đó tôi đã sử dụng "setFormattedValue" tài sản của DataTable để khắc phục vấn đề:

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

này đúng cho tôi những giá trị thích hợp cho cả hai, mặc dù nó là một chút chuyên sâu cho các tập dữ liệu lớn. Nếu có ai biết cách dễ dàng hơn để làm điều này, thì tôi sẽ rất vui khi nghe nó.

Các vấn đề liên quan