Programación de combate práctico (3): dibujo de Python del gráfico de radar de coordenadas polares

Programación de combate práctico (3): dibujo de Python del gráfico de radar de coordenadas polares

revisar

La biblioteca de dibujo matplotlib de Python es muy poderosa y puede dibujar muchos tipos de imágenes, y los gráficos de radar que encontramos en nuestra vida diaria no son una excepción.

Un gráfico de radar, también conocido como gráfico de red, gráfico de araña, gráfico estelar, etc., es un polígono irregular. Los gráficos de radar pueden mostrar vívidamente indicadores multidimensionales de lo mismo y tienen muchos escenarios de aplicación. Por ejemplo, en este blog, se utilizan para mostrar las diferencias en las diferentes habilidades de los jugadores.

El dibujo del gráfico de radar en la biblioteca matplotlib se basa en coordenadas polares , por lo que todos los datos y etiquetas deben calcularse en función de los ángulos.

Este blog explicará en detalle las ideas, procesos y análisis detallados de cada método de función en el proceso de elaboración de gráficos de radar. Si hay algún error, corríjame ~

Dibujar código y analizar

Dibujar un gráfico de radar multiagente

El llamado gráfico de radar de agentes múltiples muestra un mapa de atributos compuesto por múltiples polígonos en una imagen para formar una comparación intuitiva.

preprocesamiento

Descargue el paquete correspondiente, luego resuelva el problema de la visualización de símbolos y chinos, configure la fuente predeterminada y modifique el estilo de dibujo;

Cargue el conjunto de datos (la fuente de mi conjunto de datos aquí: una aplicación de fútbol verde), extraiga las claves y los valores en el diccionario y guárdelos en etiquetas y puntuaciones respectivamente.

import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['KaiTi']  # 指定默认字体
plt.rcParams['axes.unicode_minus'] = False  # 解决保存图像是负号'-'显示为方块的问题
plt.style.use('ggplot')  # 设置ggplot主题样式

# 原始数据集并获取数据集长度
results = [{
    
    "速度": 68, "射门": 91, "传球": 83, "盘带": 83, "防守": 47, "力量": 82},
           {
    
    "速度": 88, "射门": 87, "传球": 82, "盘带": 86, "防守": 42, "力量": 69},
           {
    
    "速度": 58, "射门": 55, "传球": 70, "盘带": 67, "防守": 86, "力量": 77}]
data_length = len(results[0])

 # 将极坐标根据数据长度进行等分,形成角度列表
angles = np.linspace(0, 2 * np.pi, data_length, endpoint=False)

# 分离属性字段和数据
labels = [key for key in results[0].keys()]
score = [[v for v in result.values()] for result in results]

Si está interesado, puede consultar este blog: Explicación detallada de plt.style.use configurando los parámetros de estilo de fondo. Elegí un tema de ggplot que creo que se ve mejor;

carta de radar cerrada

Dado que la imagen que dibujamos es un polígono cerrado, y cada elemento de los datos de puntuación, etiquetas y ángulos que extrajimos no está conectado de un extremo a otro, debemos copiar el primer elemento de cada lista y luego agregarlo al final de la lista.

angles = np.concatenate((angles, [angles[0]]))
labels = np.concatenate((labels, [labels[0]]))
score_Harry = np.concatenate((score[0], [score[0][0]]))
score_Son = np.concatenate((score[1], [score[1][0]]))
score_Tobi = np.concatenate((score[2], [score[2][0]]))

Aquí, como tengo los datos de tres jugadores, hay tres datos de puntuación.

Mencione la función np.concatenate. Esta es una función en la biblioteca numpy que fusiona múltiples matrices. El formato del parámetro es: concatenate((arr1, arr2, arr3), axis=0). El primer corchete es para fusionar. Puede completar en cualquier número de matrices. El segundo parámetro del eje está relacionado con el método de fusión. No entraremos en detalles aquí si no lo necesitamos.

dibujar imagen

Dibujar una imagen es básicamente lo mismo que dibujar un gráfico de barras, pero hay algunos puntos a tener en cuenta:

  • En la función de trazado, al dibujar un gráfico de barras, el primer y segundo parámetro se completan de acuerdo con "abscisa-ordenada". Dado que nuestro gráfico de radar se basa en coordenadas polares, matplotlib también proporciona de manera inteligente "ángulo-radio" Cómo completar los parámetros de coordenadas polares;
  • Con respecto a los parámetros de color, puede consultar esto: plt.plot enciclopedia de colores . El color en el gráfico es solo el color del borde. El color en la función de relleno es el color de relleno , que se puede combinar libremente para buscar la belleza;
  • El parámetro alfa en la función de relleno se refiere a la transparencia del área de cobertura, cuanto más pequeña es, más transparente es, el intervalo es 0-1;
  • La ubicación en la función de leyenda plt.legend describe la posición de la leyenda. Para obtener más información, consulte: Explicación detallada del ajuste de la posición de la leyenda.

El código se muestra a continuación:

# 设置图形的大小
fig = plt.figure(figsize=(8, 6), dpi=100)

# 新建一个子图
ax = plt.subplot(111, polar=True)

# 绘制雷达图并填充颜色
ax.plot(angles, score_Harry, color='orange')
ax.fill(angles, score_Harry, 'y', alpha=0.4)
ax.plot(angles, score_Son, color='b')
ax.fill(angles, score_Son, 'cyan', alpha=0.4)
ax.plot(angles, score_Tobi, color='r')
ax.fill(angles, score_Tobi, 'salmon', alpha=0.4)

# 设置雷达图中每一项的标签显示
ax.set_thetagrids(angles * 180 / np.pi, labels, fontsize=15)

ax.set_theta_zero_location('E')  # 设置0度坐标轴起始位置,东西南北

ax.set_rlim(0, 100)  # 设置雷达图的坐标刻度范围

ax.set_rlabel_position(270)  # 设置雷达图的坐标值显示角度,相对于起始角度的偏移量
ax.set_title("热刺球员能力对比图")
plt.legend(["哈里·凯恩", "孙兴愍", "托比"], loc='lower left')

plt.show()

Código completo:

import numpy as np
import matplotlib.pyplot as plt

# 解决中文显示问题
plt.rcParams['font.sans-serif'] = ['KaiTi']  # 指定默认字体
plt.rcParams['axes.unicode_minus'] = False  # 解决保存图像是负号'-'显示为方块的问题
plt.style.use('ggplot')  # 设置ggplot样式

# 原始数据集并获取数据集长度
results = [{
    
    "速度": 68, "射门": 91, "传球": 83, "盘带": 83, "防守": 47, "力量": 82},
           {
    
    "速度": 88, "射门": 87, "传球": 82, "盘带": 86, "防守": 42, "力量": 69},
           {
    
    "速度": 58, "射门": 55, "传球": 70, "盘带": 67, "防守": 86, "力量": 77}]
data_length = len(results[0])

angles = np.linspace(0, 2 * np.pi, data_length, endpoint=False)  # 将极坐标根据数据长度进行等分

# 分离属性字段和数据
labels = [key for key in results[0].keys()]
score = [[v for v in result.values()] for result in results]

# 使雷达图数据封闭
angles = np.concatenate((angles, [angles[0]]))
labels = np.concatenate((labels, [labels[0]]))
score_Harry = np.concatenate((score[0], [score[0][0]]))
score_Son = np.concatenate((score[1], [score[1][0]]))
score_Tobi = np.concatenate((score[2], [score[2][0]]))

# 设置图形的大小
fig = plt.figure(figsize=(8, 6), dpi=100)

# 新建一个子图
ax = plt.subplot(111, polar=True)

# 绘制雷达图并填充颜色
ax.plot(angles, score_Harry, color='orange')
ax.fill(angles, score_Harry, 'y', alpha=0.4)
ax.plot(angles, score_Son, color='b')
ax.fill(angles, score_Son, 'cyan', alpha=0.4)
ax.plot(angles, score_Tobi, color='r')
ax.fill(angles, score_Tobi, 'salmon', alpha=0.4)

# 设置雷达图中每一项的标签显示
ax.set_thetagrids(angles * 180 / np.pi, labels, fontsize=15)

ax.set_theta_zero_location('E')  # 设置0度坐标轴起始位置,东西南北

ax.set_rlim(0, 100)  # 设置雷达图的坐标刻度范围

ax.set_rlabel_position(270)  # 设置雷达图的坐标值显示角度,相对于起始角度的偏移量
ax.set_title("热刺球员能力对比图")
plt.legend(["哈里·凯恩", "孙兴愍", "托比"], loc='lower left')

plt.show()

El gráfico de radar final:

Insertar descripción de la imagen aquí

Sigue siendo bonita (?)

Dibuje múltiples gráficos de radar de un solo agente

La parte de procesamiento de datos es la misma que la anterior, comencemos directamente con el dibujo.

Crear un subgrafo

Primero, después de usar plt.figure para dibujar el lienzo básico, necesitamos crear tres subfiguras (porque hay tres jugadores):

ax1 = plt.subplot(131, polar=True)
ax2 = plt.subplot(132, polar=True)
ax3 = plt.subplot(133, polar=True)

Consideramos todo el lienzo como una matriz con m filas yn columnas;

El primer parámetro es un número de tres dígitos. El primer dígito indica la posición de la fila de la subimagen en todo el lienzo. 1 indica que el lienzo está dividido en 1 fila. El segundo dígito indica la columna. 3 indica que el lienzo está dividido en 3 columnas. La tercera representa el valor del índice, que se refiere a la posición específica, organizada de arriba a abajo y de izquierda a derecha. Por ejemplo, en un lienzo de 2 * 2, un valor de índice de 3 significa el primero en la segunda fila;

Recorre y dibuja cada subgrafo.

Primero, guarde las subimágenes, los datos, las etiquetas y los colores utilizados para dibujar en listas para facilitar el recorrido;

Recorre cada subgrafo:

  • Primero dibuje el eje de coordenadas angulares y la línea del marco. '-.' significa que el estilo de línea del marco se compone de un pequeño segmento de línea más un punto. lw es la abreviatura de ancho de línea, que indica el grosor de la línea;
  • Primero dibuje los contornos a lo largo de la dirección del radio y luego dibuje el eje del ángulo;
  • Dibuja y rellena con color, igual que arriba;
  • Marque el subíndice de datos, ha y va son las posiciones para ajustar las direcciones horizontal y vertical
  • Finalmente, ajuste parámetros como etiquetas, rango de valores de coordenadas, etc.
ax, data, name, color = [ax1, ax2, ax3], [score_Harry, score_Son, score_Tobi], ["哈里·凯恩", "孙兴愍", "托比"], ["orange", "cyan", "green"]

for i in range(3):
    # 绘制角度轴和框线
    for j in np.arange(0, 100+20, 20):
        ax[i].plot(angles, 7*[j], '-.', lw=0.5, color='black')  #  沿半径方向的等值线
    for j in range(5):
        ax[i].plot([angles[j], angles[j]], [0, 100], '-.', lw=0.5, color='black')  #  绘制角度轴

    # 绘制图像并填充颜色
    ax[i].plot(angles, data[i], color=color[i])
    ax[i].fill(angles, data[i], color=color[i], alpha=0.4)

    # 数据下标
    for a, b in zip(angles, data[i]):
        ax[i].text(a, b+5, '%.00f' % b, ha='center', va='center', fontsize=10, color='black')

    # 参数设置
    ax[i].set_thetagrids(angles*180/np.pi, labels)
    ax[i].set_theta_zero_location('N')
    ax[i].set_rlim(0, 100)
    ax[i].set_rlabel_position(0)
    ax[i].set_title(name[i])

Se obtiene el resultado final (la estética personal es limitada, no pulverizar si no te gusta):

Insertar descripción de la imagen aquí

En términos generales, matplotlib potente + uso flexible de código + embellecimiento = un gráfico de radar atractivo ~

Supongo que te gusta

Origin blog.csdn.net/qq_45882682/article/details/122796602
Recomendado
Clasificación