search through deeply nested objects / filtering natural earth geojson

I would like to map out countries belonging to regional groups (like ‘South Asia’, comprised of India, Bangladesh, Nepal, Bhutan, Sri Lanka and the Maldives)

I’ve downloaded the Natural Earth: Sovereign States data, converted it to geojson, and loaded it into a notebook:

Now I am stuck on how to filter down the countries to my targets. The identifying information (like country name) are nested pretty far down into the JSON object features. For example:

ne_10m_admin_0_sovereignty["features"][0]["properties"]["SOVEREIGNT"]

returns "Indonesia"

How then can I filter this object based on values in the ["SOVEREIGNT"] property?

I’ve tried looping through the object key for a match:

{
  var x = 0;
  for (let i = 0; i <= ne_10m_admin_0_sovereignty.length; i++) {
    return ne_10m_admin_0_sovereignty["features"][i]["properties"]["SOVEREIGNT"] == "Indonesia";
  }
  return x;
 }

…but I fear I’m not on the right path.

Any tips?


somewhat related discussions:

If you want to find the feature with a particular SOVEREIGNT property, you could use array.find:

ne_10m_admin_0_sovereignty.features.find(f => f.properties.SOVEREIGNT === "Indonesia")

If you want to pull out all the features with a particular SUBREGION value, you could use array.filter:

ne_10m_admin_0_sovereignty.features.filter(f => f.properties.SUBREGION === "South-Eastern Asia")

If you’re not really sure what you’re looking for and you want an overview of the data, I recommend using d3.group and experimenting with different properties that you see on each feature (by inspecting one of the features). For example:

d3.group(ne_10m_admin_0_sovereignty.features, f => f.properties.SUBREGION)
2 Likes

Awesome! Thank you @mbostock!

As a bit of follow up: How to go about adding multiple countries?

I note that the natural earth definition of the South Asia region is different than my target group. My attempt at using array find with && and/or ||, however, doesn’t seem to be capturing multiple countries.

i.e. I tried:

ne_10m_admin_0_sovereignty.features.find(f => f.properties.SOVEREIGNT === "India", f => f.properties.SOVEREIGNT === "Bhutan")

-and-

ne_10m_admin_0_sovereignty.features.find(f => f.properties.SOVEREIGNT === "India" || "Bhutan")

-and

ne_10m_admin_0_sovereignty_south_asia = ne_10m_admin_0_sovereignty.filter(function(ne_10m_admin_0_sovereignty_south_asia){
return ne_10m_admin_0_sovereignty_south_asia.features.find(f => f.properties.SOVEREIGNT === "India" ) &&
       ne_10m_admin_0_sovereignty_south_asia.features.find(f => f.properties.SOVEREIGNT === "Bhutan" )
  })

… but still coming up short.


As for my own convenient future reference: d3.group, d3.rollup

Got it!

ne_10m_admin_0_sovereignty.features.filter(f => f.properties.SOVEREIGNT === "India" || f.properties.SOVEREIGNT === "Bhutan")

Thanks again!

And I’m slowly getting closer to a sub-regional map against which to plot in various data values:

:slight_smile: More soon!

A slightly more terse method of doing that, especially once you’re looking for several countries, is this:

const southeastAsianCountries = ['India', 'Bhutan', /* ... */]
ne_10m_admin_0_sovereignty.features.filter(f => southeastAsianCountries.includes(f.properties.SOVEREIGNT))
1 Like

Excellent @j-f1! This is very helpful. Thank you!

1 Like