Enseñarle a usar Python para analizar y visualizar la red de autobuses urbanos.

1. Visualización y preprocesamiento de datos

Los datos se obtienen de la API de mapas de Gaode, que contiene los nombres de las rutas y paradas de autobús en Tianjin y sus datos de latitud y longitud .

import pandas as pd

df = pd.read_excel('site_information.xlsx')
df.head()

imagen

Campo Descripción:

  • Nombre de la línea: el nombre de la línea de autobús

  • Arriba y Abajo: 0 significa enlace ascendente; 1 significa enlace descendente

  • Número de estación: el número de serie de la línea de autobús que pasa por la estación en sentido ascendente o descendente

  • Nombre de la estación: nombre del sitio

  • Longitud (minutos): longitud del sitio

  • Latitud (minutos): latitud del sitio

Los campos de datos son pocos y la estructura es relativamente simple. Comprendamos completamente nuestros datos y realicemos un preprocesamiento. imagenEl número total de datos es 30 396. Faltan 5 nombres de estaciones, 1 falta para latitud (minutos) y 38 para longitud (minutos). Para facilitar el procesamiento, elimine las filas con valores faltantes directamente.imagen

Los datos de latitud y longitud son 7031.982 y 2348.1016, que deben convertirse a grados.

df2 = df1.copy()
df2['经度(分)'] = df1['经度(分)'].apply(float) / 60
df2['纬度(分)'] = df1['纬度(分)'].apply(float) / 60
df2.head()

imagen

En los datos procesados ​​hay un total de 618 líneas de bus y 4851 datos de estación.

imagen

Vuelva a guardar como datos procesados

df2.to_excel("处理后数据.xlsx", index=False)

2. Análisis de datos

Analizar la distribución de las estaciones de transporte público en Tianjin

# -*- coding: UTF-8 -*-
"""
@Author  :python小叮当
"""
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl
import random

df = pd.read_excel("处理后数据.xlsx")
x_data = df['经度(分)']
y_data = df['纬度(分)']
colors = ['#FF0000', '#0000CD', '#00BFFF', '#008000', '#FF1493', '#FFD700', '#FF4500', '#00FA9A', '#191970', '#9932CC']
colors = [random.choice(colors) for i in range(len(x_data))]
mpl.rcParams['font.family'] = 'SimHei'
plt.style.use('ggplot')
# 设置大小
plt.figure(figsize=(12, 6), dpi=200)
# 绘制散点图  经度  纬度  传进去   设置 颜色  点的大小
plt.scatter(x_data, y_data, marker="o", s=9., c=colors)

# 添加描述信息 x轴 y轴 标题
plt.xlabel("经度")
plt.ylabel("纬度")
plt.title("天津市公交站点分布情况")
plt.savefig('经纬度散点图.png')
plt.show()

Los resultados son los siguientes:imagen

Usando matplotlib para dibujar un diagrama de dispersión para visualizar la distribución de las estaciones de transporte público de Tianjin, es fácil ver las áreas de distribución de los puntos de acceso de transporte público de Tianjin. Para analizar la red de líneas de bus de manera más vívida, también podemos visualizar los datos en el mapa real, utilizando BMap de Pyecharts .

# -*- coding: UTF-8 -*-
"""
@Author  :python小叮当
"""
import pandas as pd
from pyecharts.charts import BMap
from pyecharts import options as opts
from pyecharts.globals import CurrentConfig

# 引用本地js资源渲染
CurrentConfig.ONLINE_HOST = 'D:/python/pyecharts-assets-master/assets/'

df = pd.read_excel('处理后数据.xlsx', encoding='utf-8')
df.drop_duplicates(subset='站名称', inplace=True)
longitude = list(df['经度(分)'])
latitude = list(df['纬度(分)'])
datas = []
a = []
for i, j in zip(longitude, latitude):
    a.append([i, j])

datas.append(a)
print(datas)

BAIDU_MAP_AK = "改成你的百度地图AK"

c = (
    BMap(init_opts=opts.InitOpts(width="1200px", height="800px"))
    .add_schema(
        baidu_ak=BAIDU_MAP_AK,     # 申请的BAIDU_MAP_AK
        center=[117.20, 39.13],    # 天津市经纬度中心
        zoom=10,
        is_roam=True,
    )
    .add(
        "",
        type_="lines",
        is_polyline=True,
        data_pair=datas,
        linestyle_opts=opts.LineStyleOpts(opacity=0.2, width=0.5, color='red'),
        # 如果不是最新版本的话可以注释下面的参数(效果差距不大)
        progressive=200,
        progressive_threshold=500,
    )
)

c.render('公交网络地图.html')

Mucha gente aprende Python y no sabe por dónde empezar.
Muchas personas aprenden Python y después de dominar la gramática básica, no saben dónde encontrar casos para comenzar.
Muchas personas que han realizado estudios de casos no saben cómo adquirir conocimientos más avanzados.
Entonces, para estos tres tipos de personas, les proporcionaré una buena plataforma de aprendizaje, ¡gratis para recibir tutoriales en video, libros electrónicos y el código fuente del curso!
Grupo QQ: 721195303

Se puede ver en el mapa real que el distrito de Heping y el distrito de Nankai tienen una densa red de líneas de autobús y un transporte conveniente.

El nodo de red de línea de bus I representa la línea i-ésima, que se define como el número de nodos que yo y yo podemos pasar a través de la línea de transferencia para llegar a una línea, el tamaño moderado de la red de línea refleja la línea de banda y otras líneas de la comunicación del bus Grado , construye un algoritmo para analizar la distribución del grado de nodo en la red de líneas de bus.

# -*- coding: UTF-8 -*-
"""
@Author  :python小叮当
"""
import xlrd
import matplotlib.pyplot as plt
import pandas as pd
import matplotlib as mpl


df = pd.read_excel("site_information.xlsx")
# 用pandas的操作去重   得到每条线路的名称
loc = df['线路名称'].unique()
# 得到每一条线路名称的列表
line_list = list(loc)
print(line_list)

# 打开Excel表格
data = xlrd.open_workbook("site_information.xlsx")
# print(data)   # <xlrd.book.Book object at 0x000001F1111C38D0> 在内存中
# 获取特定Sheet  索引为0  也就是第一个表
table = data.sheets()[0]  # 从零开始
# 每条线路对应有哪些站点  字典推导式
site_dic = {k: [] for k in line_list}
site_list = []
for i in range(1, table.nrows):
    # 每一行的数据   返回的是一个列表
    x = table.row_values(i)
    if x[1] == "0":
        # 上行   站点数据  每条线路对应有哪些站点 添加进列表
        site_dic[x[0]].append(x[3])
        site_list.append(x[3])
    else:
        continue
# print(len(site_dic))   # 618条线路
# print(len(site_list))  # 15248条站点数据
print(f"公交网络共有 {len(line_list)} 条线路")   # 618条线路

# 先初始化一个统计每个节点的度的列表  与线路名称列表里的索引一一对应
node_count = [m * 0 for m in range(len(line_list))]
# 以每条线路为一个节点  线路名称为键      值为一个列表  里面包含每条路线上行经过的所有站点
sites = [site for site in site_dic.values()]
# print(sites)
for j in range(len(sites)):  # 类似冒泡法排序  比较多少趟
    for k in range(j, len(sites) - 1):  # 每趟比较后  往后推一个  直到比较完  和防止越界
        if len(sites[j]) > len(sites[k + 1]):
            for x in sites[j]:
                if x in sites[j] and x in sites[k + 1]:   # 只要这两条线路有公共站点  节点度数加1
                    node_count[j], node_count[k + 1] = node_count[j] + 1, node_count[k + 1] + 1
                    break   # 两条线路对应在列表索引的值加1   这两条线的比较结束
        else:
            for x in sites[k + 1]:
                if x in sites[j] and x in sites[k + 1]:   # 只要这两条线路有公共站点  节点度数加1
                    node_count[j], node_count[k + 1] = node_count[j] + 1, node_count[k + 1] + 1
                    break   # 两条线路对应在列表索引的值加1   这两条线的比较结束
# print(node_count)
# 节点编号 与 节点的度数索引对应
node_number = [y for y in range(len(node_count))]
# 线性网络度的最大值   175
print(f"线路网络的度的最大值为:{max(node_count)}")
print(f"线路网络的度的最小值为:{min(node_count)}")
print(f"线路网络的度的平均值为:{sum(node_count) / len(node_count)}")
# 设置大小  图的像素
# 设置字体   matplotlib 不支持显示中文  自己本地设置
plt.figure(figsize=(10, 6), dpi=150)
mpl.rcParams['font.family'] = 'SimHei'

# 绘制每个节点度的分布
plt.bar(node_number, node_count, color="purple")

# 添加描述信息
plt.xlabel("节点编号n")
plt.ylabel("节点的度数K")
plt.title("线路网络中各节点的度的大小分布", fontsize=15)
plt.savefig("线路网络中各节点的度的大小.png")
plt.show()

Los resultados son los siguientes:

公交网络共有 618 条线路
线路网络的度的最大值为:175
线路网络的度的最小值为:0
线路网络的度的平均值为:55.41423948220065

imagen

import xlrd
import matplotlib.pyplot as plt
import pandas as pd
import matplotlib as mpl
import collections

df = pd.read_excel("site_information.xlsx")
# 用pandas的操作去重   得到每条线路的名称
loc = df['线路名称'].unique()
# 得到每一条线路名称的列表
line_list = list(loc)
print(line_list)

# 打开Excel表格
data = xlrd.open_workbook("site_information.xlsx")
# print(data)   # <xlrd.book.Book object at 0x000001F1111C38D0> 在内存中
# 获取特定Sheet  索引为0  也就是第一个表
table = data.sheets()[0]  # 从零开始
# 每条线路对应有哪些站点  字典推导式
site_dic = {k: [] for k in line_list}
site_list = []
for i in range(1, table.nrows):
    # 每一行的数据   返回的是一个列表
    x = table.row_values(i)
    if x[1] == "0":
        # 上行   站点数据  每条线路对应有哪些站点 添加进列表
        site_dic[x[0]].append(x[3])
        site_list.append(x[3])
    else:
        continue
# print(len(site_dic))   # 618条线路
# print(len(site_list))  # 15248条站点数据
# 先初始化一个统计每个节点的度的列表  与线路名称列表里的索引一一对应
node_count = [m * 0 for m in range(len(line_list))]
# 以每条线路为一个节点  线路名称为键      值为一个列表  里面包含每条路线上行经过的所有站点
sites = [site for site in site_dic.values()]
# print(sites)
for j in range(len(sites)):  # 类似冒泡法排序  比较多少趟
    for k in range(j, len(sites) - 1):  # 每趟比较后  往后推一个  直到比较完  和防止越界
        if len(sites[j]) > len(sites[k + 1]):
            for x in sites[j]:
                if x in sites[j] and x in sites[k + 1]:   # 只要这两条线路有公共站点  节点度数加1
                    node_count[j], node_count[k + 1] = node_count[j] + 1, node_count[k + 1] + 1
                    break   # 两条线路对应在列表索引的值加1   这两条线的比较结束
        else:
            for x in sites[k + 1]:
                if x in sites[j] and x in sites[k + 1]:   # 只要这两条线路有公共站点  节点度数加1
                    node_count[j], node_count[k + 1] = node_count[j] + 1, node_count[k + 1] + 1
                    break   # 两条线路对应在列表索引的值加1   这两条线的比较结束
# print(node_count)
# 节点编号 与 节点的度数索引对应
node_number = [y for y in range(len(node_count))]
# 线性网络度的最大值   175
# print(max(node_count))

# 设置大小  图的像素
# 设置字体   matplotlib 不支持显示中文  自己本地设置
plt.figure(figsize=(10, 6), dpi=150)
mpl.rcParams['font.family'] = 'SimHei'

# 分析节点的度K的概率分布
# 统计节点的度为K的 分别有多少个
node_count = collections.Counter(node_count)
node_count = node_count.most_common()
# 点
node_dic = {_k: _v for _k, _v in node_count}
# 按键从小到大排序   得到一个列表  节点的度
sort_node = sorted(node_dic)
# 按顺序得到键对应的值   即有相同节点的度的个数
sort_num = [node_dic[q] for q in sort_node]
# 概率分布中度平均值  总的度数加起来  / 个数
# print(sum(sort_node)/len(sort_node))
# 概率分布中最大的度值   也就个数最多那个
print(f"概率分布中概率最大的度值为:{max(sort_num)}")

probability = [s1 / sum(sort_num) for s1 in sort_num]   # 概率分布
print(probability)

# 天津市公交线路节点概率分布图像
plt.bar(sort_node, probability, color="red")
# 添加描述信息
plt.xlabel("节点的度K")
plt.ylabel("节点度为K的概率P(K)")
plt.title("线路网络中节点度的概率分布", fontsize=15)

plt.savefig("线路网络中节点度的概率分布.png")
plt.show()

Los resultados son los siguientes:

概率分布中概率最大的度值为:16

imagenLa distribución de grados de la red de líneas de autobús de Tianjin se muestra en la figura anterior. La red de líneas de Tianjin recopilada en este artículo consta de  618  líneas, y el valor máximo de la red de líneas es 175 . En la distribución de probabilidad, el valor grados con la mayor probabilidad es 16 , y el valor medio grado es 55.41 , lo que indica que la red de transporte público de Tianjin ofrece más oportunidades de transferencia, lo que hace que la accesibilidad superior. Entre ellos, los valores de grado con mayor probabilidad se concentran principalmente entre  7 y 26  , lo que hace que la distribución de la intensidad del nodo sea relativamente poco homogénea, lo que resulta en menos rutas de autobús en muchas secciones de Tianjin y algunas secciones con rutas de paso demasiado densas. resultando en un desperdicio de recursos.

imagenimagenEl coeficiente de agrupamiento sirve para estudiar la cercanía de la conexión entre los vecinos del nodo , por lo que no es necesario considerar la dirección del borde. Para un gráfico dirigido, trátelo como un gráfico no dirigido. El gran coeficiente de agrupamiento de la red indica que los nodos de la red tienen un alto grado de estanqueidad en relación con sus nodos cercanos, es decir, las líneas de bus están densamente conectadas a las estaciones reales. El coeficiente de agrupamiento de la red del complejo de transporte público de Tianjin se calcula en 0.091, que es más bajo que el de otras ciudades.

Según la fórmula: imagenel coeficiente de agregación de una red aleatoria de la misma escala es de aproximadamente 0,00044, lo que refleja además las características de mundo pequeño de la red .

El código de Python es el siguiente:

import xlrd
import matplotlib.pyplot as plt
import pandas as pd
import matplotlib as mpl


# 读取数据
df = pd.read_excel("site_information.xlsx")
# 用pandas的操作去重   得到每条线路的名称
loc = df['线路名称'].drop_duplicates()
# 得到每一条线路名称的列表  按照Excel表里以次下去的顺序
line_list = list(loc)
# print(line_list)

# 打开Excel表格
data = xlrd.open_workbook("site_information.xlsx")
# print(data)   # <xlrd.book.Book object at 0x000001F1111C38D0> 在内存中
# 获取特定Sheet  索引为0  也就是第一个表
table = data.sheets()[0]  # 从零开始
# 每条线路对应有哪些站点  字典推导式
site_dic = {k: [] for k in line_list}
site_list = []
for i in range(1, table.nrows):
    # 每一行的数据   返回的是一个列表
    x = table.row_values(i)
    if x[1] == "0":
        # 只取上行站点数据  每条线路对应有哪些站点 添加进列表
        site_dic[x[0]].append(x[3])
        site_list.append(x[3])
    else:
        continue
# print(len(site_dic))   # 618条线路
# print(len(site_list))  # 15248条站点数据
# 先初始化一个统计每个节点的度的列表  与线路名称列表里的索引一一对应
node_count = [m * 0 for m in range(len(line_list))]
# 以每条线路为一个节点  线路名称为键      值为一个列表  里面包含每条路线上行经过的所有站点
sites = [site for site in site_dic.values()]
# print(sites)
# 统计各节点的度
for j in range(len(sites) - 1):  # 类似冒泡法排序  比较多少趟
    for k in range(j, len(sites) - 1):  # 每趟比较后  往后推一个  直到比较完  和防止越界
        if len(sites[j]) > len(sites[k + 1]):
            for x in sites[j]:
                if x in sites[j] and x in sites[k + 1]:   # 只要这两条线路有公共站点  节点度数加1
                    node_count[j], node_count[k + 1] = node_count[j] + 1, node_count[k + 1] + 1
                    break   # 两条线路对应在列表索引的值加1   这两条线的比较结束
        else:
            for x in sites[k + 1]:
                if x in sites[j] and x in sites[k + 1]:   # 只要这两条线路有公共站点  节点度数加1
                    node_count[j], node_count[k + 1] = node_count[j] + 1, node_count[k + 1] + 1
                    break   # 两条线路对应在列表索引的值加1   这两条线的比较结束

# 找到该节点的邻居节点  邻居节点间实际的边数
Ei = []
# 对每条线路进行找邻接节点  并统计其邻接节点点实际的边数
for a in range(len(sites)):
    neighbor = []
    if node_count[a] == 0:
        Ei.append(0)
        continue
    if node_count[a] == 1:
        Ei.append(0)
        continue
    for b in range(len(sites)):
        if a == b:    # 自身  不比
            continue
        if len(sites[a]) > len(sites[b]):   # 从站点多的线路里选取站点   看是否有公共站点
            for x in sites[a]:
                if x in sites[a] and x in sites[b]:  # 找到邻居节点
                    neighbor.append(sites[b])
                    break
        else:
            for x in sites[b]:
                if x in sites[a] and x in sites[b]:  # 找到邻居节点
                    neighbor.append(sites[b])
                    break
    # 在邻居节点中判断这些节点的实际边数  又类似前面的方法  判断两两是否相连
    count = 0
    for c in range(len(neighbor) - 1):
        for d in range(c, len(neighbor) - 1):  # 每趟比较后  往后推一个  直到比较完  和防止越界
            try:
                if len(sites[c]) > len(sites[d + 1]):
                    for y in sites[c]:
                        if y in sites[c] and y in sites[d + 1]:  # 邻居节点这两个也相连
                            count += 1
                            break
                        else:
                            continue
                else:
                    for y in sites[d + 1]:
                        if y in sites[c] and y in sites[d + 1]:  # 邻居节点这两个也相连
                            count += 1
                            break
                        else:
                            continue
            except IndexError:
                break
    Ei.append(count)

# 每个节点的邻居节点间实际相连的边数
# print(Ei)
# 节点编号 与 节点的度数索引对应
node_number = [y for y in range(len(node_count))]

# 设置字体   matplotlib 不支持显示中文  自己本地设置
mpl.rcParams['font.family'] = 'SimHei'
# 设置大小  图的像素
plt.figure(figsize=(10, 6), dpi=150)
# 公交线路网络的聚类系数分布图像   相邻节点的连通程度
Ci = []
for m in range(len(node_number)):
    if node_count[m] == 0:
        Ci.append(0)
    elif node_count[m] == 1:
        Ci.append(0)

    else:  # 2 * 该节点邻居节点实际连接边数 / 最大边数
        Ci.append(2 * Ei[m] / (node_count[m] * (node_count[m] - 1)))

# 各节点邻居节点的连通程度 计算平均聚类系数
print("天津市公交线路网络平均聚类系数为:{:.4f}".format(sum(Ci) / len(Ci)))
plt.bar(node_number, Ci, color="blue")

# 添加描述信息
plt.xlabel("节点编号n")
plt.ylabel("节点的聚类系数")
plt.title("线路网络中各节点的聚类系数分布", fontsize=15)

plt.savefig("聚类系数分布.png")
plt.show()

Los resultados son los siguientes:

天津市公交线路网络平均聚类系数为:0.0906

imagen

Todavía quiero recomendar el grupo de aprendizaje de Python que construí por mí mismo : 721195303. Todos los estudiantes del grupo están aprendiendo Python. Si quieres aprender o estás aprendiendo Python, puedes unirte. Todos son parte del desarrollo de software y comparten productos de vez en cuando (solo relacionados con el desarrollo de software de Python), incluida una copia de los últimos materiales avanzados de Python y la enseñanza basada en cero compilada por mí en 2021. ¡Bienvenidos amigos que están avanzados e interesados ​​en Python a unirse!
 

Supongo que te gusta

Origin blog.csdn.net/aaahtml/article/details/114299306
Recomendado
Clasificación