Parcela yticks para tener datos de dos columnas en lugar de una sola columna

He creado un marco de datos 'predicciones' con columnas datetime, home_team, home_win, draw, away_win, away_team
datetime: Fecha del partido home_team: Nombre del equipo del hogar home_win: Probabilidad de ganar casero draw: Probabilidad del dibujo away_win: El equipo de Away gana la probabilidad away_team: Nombre del equipo de distancia

Luego traté el gráfico mencionado en la imagen usando el código mencionado a continuación:

Pero no puedo conseguir dos nombres de columna en el eje y izquierdo

Mi salida deseada es
Fecha: Home Team - Home win% - Away Team% - Away Team format

Traté de usar ax.set_yticklabels(predictions['datetime']) pero sólo mantiene el datetime y elimina el home_team nombre.

EPL Weekend Prediction

#Plotting the weekend prediction in Home Team - Home win% - Draw% - Away Team% - Away Team format

#https://stackoverflow.com/questions/34076177/matplotlib-horizontal-bar-chart-barh-is-upside-down
# the simplest solution for this problem is to reverse the pandas dataframe before plotting
predictions = predictions.iloc[::-1]

colors = sns.color_palette("pastel", n_colors=len(predictions['Home_Team']))
customPalette = sns.set_palette(sns.color_palette(colors))


colormap=cmap1,figsize=(10, 6))
ax = predictions.plot.barh(x="Home_Team", y=["home_win", "draw", "away_win"], stacked=True, colormap=customPalette,figsize=(10, 8))

ax2 = ax.twinx() #twinx() is used to have 2 different Y axes with same X axis

predictions.plot.barh(x="Away_Team", y=["home_win", "draw", "away_win"], ax=ax2,stacked=True, colormap=customPalette,figsize=(10, 8))


ax.set_title('%s Weekend Prediction : '%league_url  + today.strftime("%d-%b-%Y") + ' to ' + end_date.strftime("%d-%b-%Y"), fontsize = 18)

ax.set_ylabel('Home Team', fontsize = 14)


ax2.set_ylabel('Away Team', fontsize = 14)
#ax.set_yticklabels(y_labels_home_win)

SMALL_SIZE = 12
MEDIUM_SIZE = 14
BIGGER_SIZE = 22

plt.rc('font', size=SMALL_SIZE)          # controls default text sizes
plt.rc('xtick', labelsize=SMALL_SIZE)    # fontsize of the tick labels
plt.rc('ytick', labelsize=SMALL_SIZE)    # fontsize of the tick labels
plt.rc('legend', fontsize=SMALL_SIZE)    # legend fontsize



# move the legend
ax.legend(bbox_to_anchor=(1.25, 1), loc='upper left', borderaxespad=0.)

# Remove top and right borders
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['left'].set_visible(False)
ax.spines['bottom'].set_visible(False)

ax2.spines['top'].set_visible(False)
ax2.spines['right'].set_visible(False)
ax2.spines['left'].set_visible(False)
ax2.spines['bottom'].set_visible(False)

#https://stackoverflow.com/questions/37039685/hide-axis-values-but-keep-axis-tick-labels-in-matplotlib
rects = ax.patches  
    
for p in ax.patches:
    width, height = p.get_width(), p.get_height()
    x, y = p.get_xy() 
    ax.text(x+width/2, 
            y+height/2, 
            '{:.0%}'.format(width), 
            ha ='center', 
            va ='center')   

for p in ax2.patches:
    width, height = p.get_width(), p.get_height()
    x, y = p.get_xy() 
    ax2.text(x+width/2, 
            y+height/2, 
            '{:.0%}'.format(width), 
            ha ='center', 
            va ='center')   
ax2.get_legend().remove()
    
# Turn off tick labels
#ax.set_yticklabels([])
#ax.set_xticklabels([])
#plt.xticks([])
ax.set_xticks([])
ax2.set_xticks([])

¿Hay alguna manera de hacerlo? Puedo crear una nueva columna datetime: home_team por concatenación datetime y home_team columnas para obtener la salida deseada, pero que desorientará el marco de datos.

¿Hay una manera más simple de usar dos columnas en un solo eje?

Pregunta hecha hace 3 años, 4 meses, 27 días - Por codejuggernaut


2 Respuestas:

  • Para lograr mostrar dos columnas en el eje y de tu gráfico, puedes combinar las columnas que deseas mostrar en una sola etiqueta y luego usar esas etiquetas en el eje y. Aquí te muestro cómo puedes hacerlo:

    • Combina las columnas 'datetime', 'home_team', 'home_win', 'away_team' en una sola columna para las etiquetas del eje y.
    python
    

    Crear una nueva columna con el formato deseado para las etiquetas del eje y

    predictions['y_labels'] = predictions['datetime'].astype(str) + ' - ' + predictions['home_team'] + ' - Home Win: ' + (predictions['home_win']100).astype(str) + '% - Away Win: ' + (predictions['away_win']100).astype(str) + '%'
    • Luego, puedes utilizar esta columna 'y_labels' para establecer las etiquetas del eje y en tu gráfico.
    python
    ax.set_yticklabels(predictions['y_labels'])
    

    Al combinar las columnas en una sola, mantendrás la integridad de tu marco de datos y podrás mostrar la información deseada en el eje y de tu gráfico. Espero que esta solución te sea útil. Si necesitas más ayuda, ¡no dudes en decirme!

    Respondida el Dec 20, 2020 a las 16:52 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Usando set_yticklabels y set_yticklabels(labels, minor=True)

    Puedes usar set_yticklabels para establecer las etiquetas de ytick para el eje izquierdo y set_yticklabels(labels, minor=True) para establecer etiquetas de ytick menores para el eje derecho.

    python
    

    Establece las etiquetas del eje principal (izquierdo)

    ax.set_yticklabels(predictions['datetime'].dt.strftime("%Y-%m-%d"))

    Establece las etiquetas menores (derecha) como la combinación de "Home Team" y "Home Win"

    ax2.set_yticklabels([f"{team}: {prob100:.1f}%" for team, prob in zip(predictions['home_team'], predictions['home_win'])], minor=True)

    Usando twinx y ajustando el desplazamiento

    Otra opción es utilizar twinx para crear un segundo eje y luego ajustar el desplazamiento para superponer las etiquetas de ytick.

    python
    

    Crea un segundo eje (derecha)

    ax2 = ax.twinx()

    Ajusta el desplazamiento del segundo eje para superponer las etiquetas

    ax2.set_yticks(predictions['datetime']) ax2.yaxis.set_tick_params(pad=-20)

    Establece las etiquetas del segundo eje

    ax2.set_yticklabels(predictions['home_team'])

    Ajustes adicionales

    Para ocultar las etiquetas del segundo eje, puedes usar set_yticklabels([]). Para eliminar los bordes superior y derecho del eje, puedes usar set_frame_on(False).

    Ejemplo completo*

    python
    import matplotlib.pyplot as plt
    import pandas as pd
    
    

    Datos de ejemplo

    predictions = pd.DataFrame({ 'datetime': ['2023-03-04', '2023-03-05', '2023-03-06'], 'home_team': ['Arsenal', 'Man City', 'Chelsea'], 'home_win': [0.6, 0.7, 0.5], 'draw': [0.2, 0.1, 0.3], 'away_win': [0.2, 0.2, 0.2], 'away_team': ['Liverpool', 'Tottenham', 'Man Utd'] })

    Parcela

    fig, ax = plt.subplots(figsize=(10, 6)) customPalette = sns.set_palette(sns.color_palette("pastel", n_colors=len(predictions['home_team']))) predictions.plot.barh(x="home_team", y=["home_win", "draw", "away_win"], stacked=True, colormap=customPalette, ax=ax)

    Crea un segundo eje (derecha)

    ax2 = ax.twinx()

    Ajusta el desplazamiento del segundo eje para superponer las etiquetas

    ax2.set_yticks(predictions['datetime']) ax2.yaxis.set_tick_params(pad=-20)

    Establece las etiquetas del segundo eje

    ax2.set_yticklabels(predictions['home_team'])

    Oculta las etiquetas del segundo eje

    ax2.set_yticklabels([])

    Establece las etiquetas del eje (izquierdo)

    ax.set_yticklabels(predictions['datetime'].dt.strftime("%Y-%m-%d"))

    Elimina los bordes superior y derecho del eje

    ax.set_frame_on(False) ax2.set_frame_on(False) plt.show()

    Esto debería dar como resultado un gráfico de barras horizontales con las etiquetas de fecha y tiempo en el eje izquierdo y las etiquetas del equipo local y el porcentaje de victorias en el eje derecho.

    Respondida el Dec 20, 2020 a las 16:55 - por Gemini

    Votos positivos: 0 | Votos negativos: 0