简体   繁体   中英

How to join geojson + CSV file with omnivore leaflet in Mapbox to map data as polygons?

I have two files: 1 geojson file with the country shapes I want for a specific group of countries. 1 csv file with the data I want to map using mapbox.

I'm trying to figure out how can I join these two files so that the geojson country info name matches the countries in my CSV file. I'd like to use omnivore to convert my csv to json and then figure out how to pull that data out to bind in a popup.

There is an example of joining two geojson files (one for shapes and another for data) here: https://www.mapbox.com/mapbox.js/example/v1.0.0/choropleth-joined-data-multiple-variables/

But I'd like to use Omnivore to parse my csv file so that I can convert CSV first.

I've managed to separately load my geojson country file and load my CSV file making it ready for my highcharts pop-up, but I can't figure out how to join the two by name.

Here's how I've separately called my geojson layer:

function popup(feature, layer) {
            if (feature.properties && feature.properties.name) {
            }
        }

        $.ajax({
        dataType: "json",
        url: "countries.geojson",
        success: function(data) {
            $(data.features).each(function(key, data) {
                //transitpipes.addData(data);
        var countries = new L.geoJson(data, {
            onEachFeature: popup,
            style: countriesStyle,
        }).addTo(map);


            });
        }
        }).error(function() {});

        });

And here's what I'm trying to accomplish with my CSV data:

var ckeyOrder = []
var csvGrab2 = $.get('countries.csv',function (response) {
    Papa.parse(response, {
        complete: function(results) {
            var cHeaderRow = results.data[0];
            for (var i = 7; i < cHeaderRow.length; i++) {
            ckeyOrder.push(cHeaderRow[i])
        }
    }
    });
})
csvGrab2.done(function (csvString) {
    var countriesLayer = omnivore.csv.parse(csvString)
    countriesLayer.eachLayer(function(marker) {

        var pieChartOptions = {
            title: {
                text: null
            },
            legend: {
                enabled: false
            },
            credits: {
                enabled: false
            },
            exporting: {
                enabled: false
            },
            tooltip: {

            pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>',
                backgroundColor: {
                    linearGradient: [0, 0, 0, 60],
                    stops: [
                        [0, '#FFFFFF'],
                        [1, '#E0E0E0']
                    ]
                },
                borderWidth: 1,
                useHTML: true,
                borderColor: '#AAA'
            },

            plotOptions: {
                pie: {

                    allowPointSelect: true,
                    cursor: 'pointer',
                    connectNulls: false,
                    dataLabels: {
                                        enabled: true,
                                        format: '<b>{point.name}</b>: {point.percentage:.1f} %',
                                        style: {
                                            color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'
                                        }
                                    }
                }
            }
        };

         pieChartOptions.tooltip.formatter = function() {
                var y = "" + this.y;
                return '<center>' + y + '</center>';
            };
        var cData = [];
        for (var i = 0; i < ckeyOrder.length; i++) {
           cData.push(parseInt(marker.feature.properties[ckeyOrder[i]]))
        }

        var lastColumn = ckeyOrder.length;
        pieChartOptions.series = [{
            data: cData
        }];
         // HTML content for country pop-up
        var countryContent = '<div id="popup_template">' +
            '<div>' +marker.toGeoJSON().properties.Name +'</div>' +
            '<div><p>'+marker.toGeoJSON().properties.Production+'</p></div>'+

            '<div id="piechart"></div>';
        var ccontainer = $('<div id="popup_template"/>');
        ccontainer.html( '<div>' +marker.toGeoJSON().properties.Name +'</div>' +
            '<div><p>'+marker.toGeoJSON().properties.Production +'</p></div>' +
            '<div id="piechart"></div>');
        // Delegate all event handling for the container itself and its contents to the container
        ccontainer.find('#piechart').highcharts(lineChartOptions);
        marker.bindPopup(ccontainer[0]);

Is there a way to join my geojson countries with my omnivore parsed CSV code so that I can map my CSV data this way?

My incredible bad attempt at this mix of code is here: https://jsfiddle.net/t8qsbzs0/

Here is my CSV structure (one row):

Country,Production,Gas demand,Total imports,of which LNG,Total exports,Total storage capacity,Share of gas in TPES (%),Self sufficiency (%),Electricity and heat,Industry,Residential,Services,Other
France,0.3,44,47.9,7.8,5,12.1,15.1,0.7,16,26,33,18,7

and my countries.geojson file is structured like this:

{"type":"Feature","properties":{"name":"France","iso_a2":"FR","iso_a3":"FRA","iso_n3":"250"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-52.6,2.5],[-52.9,2.1],[-53.4,2.1],[-53.6,2.3],[-53.8,2.4],[-54.1,2.1],[-54.5,2.3],[-54.3,2.7],[-54.2,3.2],[-54,3.6],[-54.4,4.2],[-54.5,4.9],[-54,5.8],[-53.6,5.6],[-52.9,5.4],[-51.8,4.6],[-51.7,4.2],[-52.2,3.2],[-52.6,2.5]]],[[[9.6,42.2],[9.2,41.4],[8.8,41.6],[8.5,42.3],[8.7,42.6],[9.4,43],[9.6,42.2]]],[[[3.6,50.4],[4.3,49.9],[4.8,50],[5.7,49.5],[5.9,49.4],[6.2,49.5],[6.7,49.2],[8.1,49],[7.6,48.3],[7.5,47.6],[7.2,47.4],[6.7,47.5],[6.8,47.3],[6,46.7],[6,46.3],[6.5,46.4],[6.8,46],[6.8,45.7],[7.1,45.3],[6.7,45],[7,44.3],[7.5,44.1],[7.4,43.7],[6.5,43.1],[4.6,43.4],[3.1,43.1],[3,42.5],[1.8,42.3],[0.7,42.8],[0.3,42.6],[-1.5,43],[-1.9,43.4],[-1.4,44],[-1.2,46],[-2.2,47.1],[-3,47.6],[-4.5,48],[-4.6,48.7],[-3.3,48.9],[-1.6,48.6],[-1.9,49.8],[-1,49.3],[1.3,50.1],[1.6,50.9],[2.5,51.1],[2.7,50.8],[3.1,50.8],[3.6,50.4]]]]}},

Okay, so yes, once the content of pie chart is decided..this "joining" is pretty easy.

Entire code block is here in a JSFiddle - https://jsfiddle.net/j4fLj5gm/1/ Won't work because of the CORS issue mentioned in comments, but posting it here for anyway.

The join happens with a loop through actual data, and then a search through the Leaflet feature layer to find the match for the country name.

for (var countryIndex = 0; countryIndex < countryData.length; countryIndex++) {
  var marker;
  var thisDataRow = countryData[countryIndex];
  var thisCountry = thisDataRow[0];
  countries.eachLayer(function(country) {
    if (country.feature.properties.name === thisCountry) {
      marker = country;
    }
  })
  if (typeof marker == 'undefined') {
    continue;
  }

Data prep for the pie chart is quite easy inside each country's loop.

  var cData = [];
  var innerIndex = 0;
  for (var i = 9; i < 14; i++) {
     cData.push({name: ckeyOrder[innerIndex],y: parseInt(thisDataRow[i])})
     innerIndex++;
  }

  pieChartOptions.series = [{
      Name: "Production Types",
      data: cData
  }];

Results in below screenshot..You will probably want to control a dimensions a bit. 在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM