Рубрики
Без рубрики

Практическое введение в графики (сетевые диаграммы)

График представляет собой структуру, представляющую соединения между объектами. Они могут быть использованы для социальных … Теги с Python, начинающими, учебниками, CodeNewie.

График представляет собой структуру, представляющую соединения между объектами. Они могут быть использованы для анализа социальной сети, разработка чьего-либо Erdős номер , найти кратчайший путь через лабиринт, и многие другие Приложения Отказ

Мы рассмотрим путь между двумя странами с наименьшими пограничными переходами. Метод, который мы будем использовать Широк-первый поиск (BFS).

Что на графике?

Графики состоят из вершин и краев. Ниже приведено представление Франции и его земельных пограничных переездов.

Пример вершины – О или Департамент – Они также известны как точки или узлы. Здесь они представляют страны.

Пример края – {Fr, это} или {Fr, будь} – Они также известны как линии, ссылки или соединения. Здесь они представляют собой землю пересечение границы между двумя странами.

Давайте построим немного более сложный график. Если наша цель – найти кратчайший путь между двумя странами, тогда нам нужна структура, содержащая все страны мира. На самом деле нам нужны несколько графиков, потому что некоторые наборы стран не связаны с другими наборами стран (и острова – просто одинокие вершины).

Весь код для этого поста можно найти на Healleycodes/Country-Borders Отказ

Мы можем получить все данные, которые нам нужны от Borders.csv Отказ Этот файл структурирован как country_code, country_name, country_berder_code, country_berder_name Отказ

В качестве бокового квеста мы также будем хранить отношения между кодами стран и их полными именами, чтобы сделать наш выход более удобным позже.

import csv

country_border_graph = {}
country_code_lookup = {}

with open('borders.csv') as csvfile:
    reader = csv.reader(csvfile, delimiter=',')
    next(reader, None)  # skip the headers
    for row in reader:
        country_code_lookup[row[0]] = row[1]
        country_a = row[0]
        country_b = row[2]

        if country_a in country_border_graph:
            country_border_graph[country_a].append(country_b)
        else:
            country_border_graph[country_a] = [country_b]

График – это математическая структура, и нет особых способов представлять их в коде. Здесь мы выбрали словарь, который отображает страну в список своих соседей.

Если мы изолируем Францию внутри country_border_graph Похоже, это выглядит так:

{
    'FR': ['AD', 'BE', 'DE', 'IT', 'LU', 'MC', 'ES', 'CH']
}

Отображение графов

Итак, как мы печатаем это на экран? Сначала мы изменим структуру наших данных, то мы подключаем его к некоторым библиотекам.

Для того, чтобы построить Dataframe для Пандас Библиотека, нам нужно создать два списка, которые описывают все наши края. Мы делаем это, итерацию через структуру и добавляя вершину до двух списков ( from_verts и to_verts ) Когда мы хотим описать соединение.

from_verts = []
to_verts = []
for country in country_border_graph:
    for i in range(0, len(country_border_graph[country])):
        if country_border_graph[country][0] == '':
            # skip islands
            continue
        from_verts.append(country)
        to_verts.append(country_border_graph[country][i])

Для Франции списки будут выглядеть так:

# from_verts
['FR', 'FR', 'FR', 'FR', 'FR', 'FR', 'FR', 'FR']

# to_verts
['AD', 'BE', 'DE', 'IT', 'LU', 'MC', 'ES', 'CH']

Использование Пандас , ettewxx и matplotlib. Мы можем показать ваши невынастинные острова в всплывающем окне.

import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt


def show(from_verts, to_verts):
    df = pd.DataFrame(
        {'from': from_verts, 'to': to_verts})
    G = nx.from_pandas_edgelist(df, 'from', 'to')

    nx.draw(G,
            with_labels=True,
            node_size=1500,
            node_color="skyblue",
            node_shape="o",
            linewidths=4,
            font_size=25,
            font_color="grey",
            font_weight="bold",
            width=4,
            edge_color="grey",
            dpi=1000)
    plt.show()

Результат ниже. (Я кратко попытался визуально unquiscish Вершины друг от друга, но не думали, что это стоило усилий. Если вы хотите отобразить эти данные более эстетически, начните с проверки этого Ответ в Stackoverflow .)

Хотя это изображение, на первый взгляд, выглядит похоже на карту мира, позиции стран не привязаны к их позиции на земле.

Кратчайшие пути

Вы можете рассчитать кратчайший путь между некоторыми странами вручную. Возьмите путь от Канады в Мексику в качестве примера. В самой низкой точке крупнейшего набора на приведенном выше изображении мы можем видеть, что CA подключен к США который подключен к MX Отказ Ясно, что есть только один маршрут между Канадой и Мексикой, и поэтому мы нашли кратчайший путь.

Что если есть несколько путей? Давайте наступим путь от Франции в Китай в качестве примера.

Первый поиск по широту (BFS) работает сначала взглядом на все соседние вершины, а затем работать дальше и дальше от начальной точки. Используя FR В качестве отправной точки наш алгоритм будет сначала проверить [«AD», «Будь», «de», «Это», «Лу», «MC», «ES», «CH»] Отказ Когда он не найдет Китае среди тех, он потом посмотрит на соседей Ad а потом соседи Быть и так далее.

На диаграмме ниже мы можем увидеть заказ, в котором BFS будет посещать каждую вершину дерева.

Алгоритм, который мы используем, было адаптировано из Устаревший эссе на python.org. Eryk Kopczyński исправил эффективность функции пути эссе на десять лет после даты публикации. В линейном времени он вычисляет и хранит прямые пути от начальной точки до любой точки, а затем возвращает путь от начальной точки в конечную точку.

Его оригинальный код возвращает путь в странном формате. FR к Составлять это [[[[[«ФР»], «de '],' pl '],' ru '],' cn '] . Мы можем развернуть этот вложенный список с сплющить .

from collections import Iterable


def flatten(l):
    # flatten a nested list
    # https://stackoverflow.com/a/2158532

    for el in l:
        if isinstance(el, Iterable) and not isinstance(el, (str, bytes)):
            yield from flatten(el)
        else:
            yield el


def find_shortest_path(graph, start, end):
    # breadth first search (BFS)
    # adapted from https://www.python.org/doc/essays/graphs/

    dist = {start: [start]}
    q = [start]
    while len(q):
        at = q.pop(0)
        for country in graph[at]:
            if country not in dist:
                dist[country] = [dist[at], country]
                q.append(country)

    raw_path = dist.get(end)
    return list(flatten(dist.get(end)))

Мы можем использовать эту функцию на оригинале country_border_graph Словарь мы построили. С country_code_lookup Мы сделали, мы можем распечатать удобную информацию.

france = country_border_graph["FR"]
france_names = [country_code_lookup[code] for code in france]

print(f'France is connected to {len(france_names)} countries.')
print(f'They are {", ".join(france_names)}.')

path = find_shortest_path(country_border_graph, 'FR', 'CN')
path_names = [country_code_lookup[code] for code in path]

print(f'The shortest path from France to China is: {" -> ".join(path_names)}.')

Это отпечатки:

France is connected to 8 countries.
They are Andorra, Belgium, Germany, Italy, Luxembourg, Monaco, Spain, Switzerland.
The shortest path from France to China is: France -> Germany -> Poland -> Russian Federation -> China.

Чтобы отобразить этот путь, мы можем использовать Показать функция Мы определили ранее.

path = find_shortest_path(country_border_graph, 'FR', 'CN')

from_verts = []
to_verts = []
for i in range(1, len(path)):
    # we're drawing a line
    # so we describe each edge 
    from_verts.append(path[i-1])
    to_verts.append(path[i])

graph.show(from_verts, to_verts)

Теперь мы можем визуально показать кратчайший путь между любыми двумя связанными странами.

(Если мы попытались использовать этот код для расчета пути между двумя не связанными странами, например GB и CN код будет бросать ошибку. Давайте винить географию для этого вместо автор кода.)

Благодаря Александр Дрихель для черной древовидной диаграммы дерева.

Присоединяйтесь к 300+ людям зарегистрировано на мой рассылка О коде и как я пишу!

Я Tweet о Tech @healecodes Отказ

Оригинал: “https://dev.to/healeycodes/a-practical-introduction-to-graphs-network-diagrams-b2b”