Seaborn Barplot - Visualización de valores

Quiero ver cómo hacer dos cosas en Seaborn con el uso de un gráfico de barras para mostrar los valores que están en el marco de datos, pero no en el gráfico

  1. Quiero mostrar los valores de un campo en un marco de datos mientras grafico otro. Por ejemplo, abajo, estoy graficando 'propina', pero me gustaría colocar el valor de 'factura_total' centrado sobre cada una de las barras (i.e.325.88 sobre viernes, 1778,40 sobre el sábado, etc.)

  2. ¿Hay alguna forma de escalar los colores de las barras, de forma que el valor más bajo de 'total_bill' tenga el color más claro (en este caso el viernes) y el valor más alto de 'total_bill' tenga el más oscuro? Obviamente, yo me quedaría con un color (por ejemplo, azul) al hacer el escalado.

Gracias. I'm sure this is easy, but i'm missing it..

**Aunque veo que otros piensan que esto es un duplicado de otro problema (o dos), me falta la parte de cómo uso un valor que no está en el gráfico como base para la etiqueta o el sombreado. Como digo, usar total_bill como base. Lo siento, pero no puedo entenderlo basándome en estas respuestas.

Empezando con el siguiente código,

import pandas as pd
import seaborn as sns
%matplotlib inline
df=pd.read_csv("https://raw.githubusercontent.com/wesm/pydata-    book/master/ch08/tips.csv", sep=',')
groupedvalues=df.groupby('day').sum().reset_index()
g=sns.barplot(x='day',y='tip',data=groupedvalues)

Obtengo el siguiente resultado:

Solución provisional:

for index, row in groupedvalues.iterrows():
    g.text(row.name,row.tip, round(row.total_bill,2), color='black', ha="center")

En el shading, utilizando el ejemplo de abajo, he intentado lo siguiente:

import pandas as pd
import seaborn as sns
%matplotlib inline
df=pd.read_csv("https://raw.githubusercontent.com/wesm/pydata-book/master/ch08/tips.csv", sep=',')
groupedvalues=df.groupby('day').sum().reset_index()

pal = sns.color_palette("Greens_d", len(data))
rank = groupedvalues.argsort().argsort() 
g=sns.barplot(x='day',y='tip',data=groupedvalues)

for index, row in groupedvalues.iterrows():
    g.text(row.name,row.tip, round(row.total_bill,2), color='black', ha="center")

Pero eso me dio el siguiente error:

AttributeError: 'DataFrame' object has no attribute 'argsort'

Así que probé con una modificación:

import pandas as pd
import seaborn as sns
%matplotlib inline
df=pd.read_csv("https://raw.githubusercontent.com/wesm/pydata-book/master/ch08/tips.csv", sep=',')
groupedvalues=df.groupby('day').sum().reset_index()

pal = sns.color_palette("Greens_d", len(data))
rank=groupedvalues['total_bill'].rank(ascending=True)
g=sns.barplot(x='day',y='tip',data=groupedvalues,palette=np.array(pal[::-1])[rank])

y eso me deja con

IndexError: index 4 is out of bounds for axis 0 with size 4

Solución

Vamos a ceñirnos a la solución de la pregunta enlazada (Changing color scale in seaborn bar plot). Quieres usar argsort para determinar el orden de los colores a usar para colorear las barras. En la pregunta enlazada argsort se aplica a un objeto Series, lo que funciona bien, mientras que aquí tienes un DataFrame. Así que tienes que seleccionar una columna de ese DataFrame para aplicar argsort.

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np

df = sns.load_dataset("tips")
groupedvalues=df.groupby('day').sum().reset_index()

pal = sns.color_palette("Greens_d", len(groupedvalues))
rank = groupedvalues["total_bill"].argsort().argsort() 
g=sns.barplot(x='day',y='tip',data=groupedvalues, palette=np.array(pal[::-1])[rank])

for index, row in groupedvalues.iterrows():
    g.text(row.name,row.tip, round(row.total_bill,2), color='black', ha="center")

plt.show()


El segundo intento funciona bien también, el único problema es que el rango devuelto por `rank()` comienza en `1` en lugar de cero. Así que hay que restar 1 al array. Además para indexar necesitamos valores enteros, así que tenemos que convertirlo a `int`.
rank = groupedvalues['total_bill'].rank(ascending=True).values
rank = (rank-1).astype(np.int)
Comentarios (0)

Funciona con un solo eje o con una matriz de ejes (subparcelas)

from matplotlib import pyplot as plt
import numpy as np

def show_values_on_bars(axs):
    def _show_on_single_plot(ax):        
        for p in ax.patches:
            _x = p.get_x() + p.get_width() / 2
            _y = p.get_y() + p.get_height()
            value = '{:.2f}'.format(p.get_height())
            ax.text(_x, _y, value, ha="center") 

    if isinstance(axs, np.ndarray):
        for idx, ax in np.ndenumerate(axs):
            _show_on_single_plot(ax)
    else:
        _show_on_single_plot(axs)

fig, ax = plt.subplots(1, 2)
show_values_on_bars(ax)
Comentarios (1)

Espero que esto ayude para el punto #2: a) Puede ordenar por factura total y luego reajustar el índice a esta columna b) Use palette="Blue" para usar este color para escalar su gráfico de azul claro a azul oscuro (si es azul oscuro a azul claro entonces use palette="Blues_d")

import pandas as pd
import seaborn as sns
%matplotlib inline

df=pd.read_csv("https://raw.githubusercontent.com/wesm/pydata-book/master/ch08/tips.csv", sep=',')
groupedvalues=df.groupby('day').sum().reset_index()
groupedvalues=groupedvalues.sort_values('total_bill').reset_index()
g=sns.barplot(x='day',y='tip',data=groupedvalues, palette="Blues")
Comentarios (2)