Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting the population of a city given its name

What is a good python API I can use to get the population of a city? I have tried using geocoder, but it is not working - not sure why.

geocoder.population('San Francisco, California')

returns

'module' object has no attribute 'population'

Why is this happening, and how can I fix it?

Alternatively, is there a different python api I can use for this?

like image 685
Frick Steves Avatar asked Feb 20 '17 01:02

Frick Steves


1 Answers

Certainly you can get the population of a city using geocoder and Google, but it requires an API key.

Here are two quite different alternative solutions:

OpenDataSoft

The first solution uses the OpenDataSoft API and basic Python 3.

The country needs to be specified via a two-letter country code, see examples below.

import requests
import json

def get_city_opendata(city, country):
    tmp = 'https://public.opendatasoft.com/api/records/1.0/search/?dataset=worldcitiespop&q=%s&sort=population&facet=country&refine.country=%s'
    cmd = tmp % (city, country)
    res = requests.get(cmd)
    dct = json.loads(res.content)
    out = dct['records'][0]['fields']
    return out

get_city_opendata('Berlin', 'de')

#{'city': 'berlin',
# 'country': 'de',
# 'region': '16',
# 'geopoint': [52.516667, 13.4],
# 'longitude': 13.4,
# 'latitude': 52.516667,
# 'accentcity': 'Berlin',
# 'population': 3398362}

get_city_opendata('San Francisco', 'us')

#{'city': 'san francisco',
# 'country': 'us',
# 'region': 'CA',
# 'geopoint': [37.775, -122.4183333],
# 'longitude': -122.4183333,
# 'latitude': 37.775,
# 'accentcity': 'San Francisco',
# 'population': 732072}

WikiData

The second solution uses the WikiData API and the qwikidata package.

Here, the country is given by its English name (or a part of it), see examples below.

I'm sure the SPARQL command can be written much more efficiently and elegantly (feel free to edit), but it does the job.

import qwikidata
import qwikidata.sparql

def get_city_wikidata(city, country):
    query = """
    SELECT ?city ?cityLabel ?country ?countryLabel ?population
    WHERE
    {
      ?city rdfs:label '%s'@en.
      ?city wdt:P1082 ?population.
      ?city wdt:P17 ?country.
      ?city rdfs:label ?cityLabel.
      ?country rdfs:label ?countryLabel.
      FILTER(LANG(?cityLabel) = "en").
      FILTER(LANG(?countryLabel) = "en").
      FILTER(CONTAINS(?countryLabel, "%s")).
    }
    """ % (city, country)

    res = qwikidata.sparql.return_sparql_query_results(query)
    out = res['results']['bindings'][0]
    return out

get_city_wikidata('Berlin', 'Germany')

#{'city': {'type': 'uri', 'value': 'http://www.wikidata.org/entity/Q64'},
# 'population': {'datatype': 'http://www.w3.org/2001/XMLSchema#decimal',
#  'type': 'literal',
#  'value': '3613495'},
# 'country': {'type': 'uri', 'value': 'http://www.wikidata.org/entity/Q183'},
# 'cityLabel': {'xml:lang': 'en', 'type': 'literal', 'value': 'Berlin'},
# 'countryLabel': {'xml:lang': 'en', 'type': 'literal', 'value': 'Germany'}}

get_city_wikidata('San Francisco', 'America')

#{'city': {'type': 'uri', 'value': 'http://www.wikidata.org/entity/Q62'},
# 'population': {'datatype': 'http://www.w3.org/2001/XMLSchema#decimal',
#  'type': 'literal',
#  'value': '805235'},
# 'country': {'type': 'uri', 'value': 'http://www.wikidata.org/entity/Q30'},
# 'cityLabel': {'xml:lang': 'en', 'type': 'literal', 'value': 'San Francisco'},
# 'countryLabel': {'xml:lang': 'en',
#  'type': 'literal',
#  'value': 'United States of America'}}

Both approaches return dictionaries from which you can extract the infos you need using basic Python.

Hope that helps!

like image 131
David Avatar answered Nov 04 '22 23:11

David