1
votes

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]]]]}},
1
Can you fix the error on map.legendControl.addLegend(document.getElementById('legend').innerHTML); first?see dev consolesnkashis
Hi sorry @snkashis I left that in after removing the legend. Thanks for looking at this! Here's a cleaner copy: jsfiddle.net/t8qsbzs0/4illusk
Maybe I am missing something, but how is that question connected to the Highcharts library?Paweł Fus
@PawełFus I am using the data to chart a highcharts pie graph on popupillusk
@illusk can you add your geojson and csv content as external resources stored inside of 2 separate variables so we can avoid the current 404s on load? you can return to ajax logic later.snkashis

1 Answers

1
votes

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. enter image description here