OSMnx: нормализованная мера порядка ориентации - PullRequest
0 голосов
/ 09 мая 2020

Привет, я пытаюсь вычислить нормализованный порядок ориентации

  • Сначала вычислите пеленги каждого края уличной сети в 36 интервалов равного размера (представляющих 360 градусов с каждым интервалом, представляющим 10 градусов)

с использованием

import datetime
import matplotlib.pyplot as plt
import numpy as np
import osmnx as ox
import pandas as pd

ox.config(log_console=True, use_cache=True)
weight_by_length = False

places = {'Atlanta'       : 'Atlanta, GA, USA'}

# verify OSMnx geocodes each query to what you expect (a [multi]polygon geometry)
gdf = ox.gdf_from_places(places.values())
gdf

def reverse_bearing(x):
    return x + 180 if x < 180 else x - 180

bearings = {}
for place in sorted(places.keys()):
    print(datetime.datetime.now(), place)

    # get the graph
    query = places[place]
    G = ox.graph_from_place(query, network_type='drive')

    # calculate edge bearings
    Gu = ox.add_edge_bearings(ox.get_undirected(G))

    if weight_by_length:
        # weight bearings by length (meters)
        city_bearings = []
        for u, v, k, d in Gu.edges(keys=True, data=True):
            city_bearings.extend([d['bearing']] * int(d['length']))
        b = pd.Series(city_bearings)
        bearings[place] = pd.concat([b, b.map(reverse_bearing)]).reset_index(drop='True')
    else:
        # don't weight bearings, just take one value per street segment
        b = pd.Series([d['bearing'] for u, v, k, d in Gu.edges(keys=True, data=True)])
        bearings[place] = pd.concat([b, b.map(reverse_bearing)]).reset_index(drop='True')

def count_and_merge(n, bearings):
    # make twice as many bins as desired, then merge them in pairs
    # prevents bin-edge effects around common values like 0° and 90°
    n = n * 2
    bins = np.arange(n + 1) * 360 / n
    count, _ = np.histogram(bearings, bins=bins)

    # move the last bin to the front, so eg 0.01° and 359.99° will be binned together
    count = np.roll(count, 1)
    return count[::2] + count[1::2]

Когда я выполняю

count_and_merge(36, bearings['Atlanta'])

, я получаю (я считаю, что количество ребер в каждой ячейке)

array([4400,  768,  617,  631,  614,  601,  613,  672,  781, 4405,  813,
    577,  609,  602,  614,  591,  739,  814, 4400,  768,  617,  631,
    614,  601,  613,  672,  781, 4405,  813,  577,  609,  602,  614,
    591,  739,  814])

Затем я вычисляю энтропию, используя

    data = [4400,  768,  617,  631,  614,  601,  613,  672,  781, 4405,  813,
            577,  609,  602,  614,  591,  739,  814, 4400,  768,  617,  631,
            614,  601,  613,  672,  781, 4405,  813,  577,  609,  602,  614,
            591,  739,  814]
pd_series = pd.Series(data)
counts = pd_series.value_counts()
entropy(counts)

Я получил 2,8133554045006157

Когда я нормализую его, используя

=1-((2.81-1.38)/2.198)^2

Ответ: 0.57

Что немного больше 0,3 (что указано в https://link.springer.com/content/pdf/10.1007/s41109-019-0189-1.pdf)

есть предложения?

1 Ответ

1 голос
/ 11 мая 2020

Я автор статьи в журнале, на которую вы ссылаетесь, и кода исследования, который вы хотите адаптировать. Чтобы использовать этот код для города Атланта, просто адаптируйте его из записной книжки и добавьте уравнение порядка ориентации из статьи журнала , например:

import numpy as np
import osmnx as ox
import pandas as pd
from scipy import stats
ox.config(use_cache=True, log_console=True)

query = 'Atlanta, GA, USA'
entropy_bins = 36

def reverse_bearing(x):
    return x + 180 if x < 180 else x - 180

def count_and_merge(n, bearings):
    n = n * 2
    bins = np.arange(n + 1) * 360 / n
    count, _ = np.histogram(bearings, bins=bins)
    count = np.roll(count, 1)
    return count[::2] + count[1::2]

Gu = ox.add_edge_bearings(ox.get_undirected(ox.graph_from_place(query, network_type='drive')))
b = pd.Series([d['bearing'] for u, v, k, d in Gu.edges(keys=True, data=True)])
bearings = pd.concat([b, b.map(reverse_bearing)]).reset_index(drop='True')
bin_counts = count_and_merge(entropy_bins, bearings)
orientation_entropy = stats.entropy(bin_counts)

perfect_grid = [1] * 4 + [0] * (entropy_bins - 4)
min_entropy = stats.entropy(perfect_grid)
max_entropy = np.log(entropy_bins)    
orientation_order = 1 - ((orientation_entropy - min_entropy) / (max_entropy - min_entropy)) ** 2
print(orientation_order) #0.3115
...