UK Postcode to Census Data using the API

半腔热情 提交于 2019-12-08 03:04:04

问题


Using the Office for National Statistics website I can get a census summary for a UK postcode.

https://neighbourhood.statistics.gov.uk/dissemination/

I expected that I should be able to do the same thing using the API.

https://neighbourhood.statistics.gov.uk/HTMLDocs/downloads/QuickStart-Guide-V2.1.pdf

But it isn't clear to me how to get from the postcode to the neighbourhood (or Lower Layer Super Output Area as the Office for National Statistics calls them). It seems that I need to use the Delivery endpoint like this.

http://neighbourhood.statistics.gov.uk/NDE2/Deli/getChildAreaTables?ParentAreaId=276980&LevelTypeId=141&Datasets=67

But how do I find out which parameters to use for a specific postcode?


回答1:


It looks like three calls are required to get a dataset.

import xml.etree.ElementTree as ElementTree
import json
import requests
API_KEY = "YOUR_API_KEY"

def get_area_id(level_type, postcode):
    """ Get the area id for the pos

    :param level_type: The resolution you are interested in. 14 = ward level data.
    :param postcode: A UK postcode
    :return: string area identifier
    """
    base_url = "http://neighbourhood.statistics.gov.uk/NDE2/Disco/FindAreas"
    payload = {'HierarchyId': '27', 'Postcode': postcode}
    response = requests.get(base_url, params=payload)
    xml = ElementTree.fromstring(response.content)
    namespaces = {'ns1': 'http://neighbourhood.statistics.gov.uk/nde/v1-0/discoverystructs'}
    xpath_for_area = './/ns1:Area'
    areas = xml.findall(xpath_for_area, namespaces)
    ward_area_id = ''
    for area in areas:
        level_type_id = area.find('ns1:LevelTypeId', namespaces).text
        if level_type_id == str(level_type):  # find the Ward (=14)
            ward_area_id = area.find('ns1:AreaId', namespaces).text
    return ward_area_id

def get_ext_code(area_id):
    """ Get the ext code (whatever that is) from an area id

    :param area_id: the area id for a postcode
    :return: the ext code for an area (I think is the GSS code)
    """
    base_url = "http://neighbourhood.statistics.gov.uk/NDE2/Disco/GetAreaDetail"
    payload = {'AreaId': area_id}
    response = requests.get(base_url, params=payload)
    xml = ElementTree.fromstring(response.content)
    namespaces = {'ns1': 'http://neighbourhood.statistics.gov.uk/nde/v1-0/discoverystructs',
              'structure': 'http://www.SDMX.org/resources/SDMXML/schemas/v2_0/structure'}
    xpath_for_ext_code = './/ns1:ExtCode'
    ext_code = xml.find(xpath_for_ext_code, namespaces).text
    return ext_code

def get_data(data_set, geog_code):
    """ Get the data for a geographical code

    :param data_set: string identifier from http://www.nomisweb.co.uk/census/2011 /quick_statistics
    :param geog_code: the ext code for the geographical area
    :return: a json object with the data
    """
    base_url = "http://data.ons.gov.uk/ons/api/data/dataset/"
    payload = {'apikey': API_KEY, 'context': 'Census', 'geog': '2011WARDH', 'dm/2011WARDH': geog_code,
               'totals': 'false', 'jsontype': 'json-stat'}
    r = requests.get(base_url + "/" + data_set + ".json", params=payload)
    obj = json.loads(r.text)
    return obj

def process(json_object, data_set):
    data = {}
    values = json_object[data_set]['value']
    index = json_object[data_set]['dimension'][json_object[data_set]['dimension']['id'][1]]['category']['index']
    labels = json_object[data_set]['dimension'][json_object[data_set]['dimension']['id'][1]]['category']['label']
    for l in labels:
        num = index[l]
        count = values[str(num)]
        data[labels[l]] = count
    return data

area_id = get_area_id(14, "SW1A 0AA")
gss_code = get_ext_code(area_id)
data_returned = get_data("QS208EW", gss_code)  # QS208EW = religion

print(process(data_returned, "QS208EW"))



回答2:


Have you tried looking at the code in the VBA example?

Function RunAreas()
    Dim txtResponse
    Dim postcode As String
    Dim extCode
    Set rootSheet = GetSheet("Query")
    Set areaSheet = GetSheet("Areas")
    endPoint = "http://neighbourhood.statistics.gov.uk/NDE2/Disco/FindAreas?HierarchyId=27&Postcode="
    postcode = rootSheet.Range("A2").Value
    Application.StatusBar = "Getting areas for " + postcode
    txtResponse = GetAreas(postcode)
    delim = "<delim>"
    data = GetElements(txtResponse, "Area")

    If UBound(data) < 0 Then
        Application.StatusBar = False
        MsgBox "Postcode " + postcode + " not found", vbExclamation
        Exit Function
    End If

    For i = 0 To UBound(data)
        curLevelType = GetValue(data(i), "LevelTypeId")
        curHierarchy = GetValue(data(i), "HierarchyId")
        curId = GetValue(data(i), "AreaId")
        curName = GetValue(data(i), "Name")

        Select Case curLevelType
        Case 15
            extCode = UpdateArea("Output Area", 2, curId, curName, curHierarchy)
        Case 14
            extCode = UpdateArea("Ward", 3, curId, curName, curHierarchy)
        Case 13
            extCode = UpdateArea("LA", 4, curId, curName, curHierarchy)
        Case 11
            extCode = UpdateArea("Region", 5, curId, curName, curHierarchy)
        Case 10
            extCode = UpdateArea("Country", 6, curId, curName, curHierarchy)
        End Select

    Next

    MsgBox ("Areas Found")
    Application.StatusBar = "Get Areas completed"

End Function


来源:https://stackoverflow.com/questions/29622849/uk-postcode-to-census-data-using-the-api

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!