Gráfico jerárquico de tarta / buñuelo de Pandas DataFrame usando bokeh o matplotlib

Tengo el siguiente dataframe de pandas (“A” es el encabezado de la última columna; el rest de las columnas son un índice jerárquico combinado):

A kingdom phylum class order family genus species No blast hit 2496 k__Archaea p__Euryarchaeota c__Thermoplasmata o__E2 f__[Methanomassiliicoccaceae] g__vadinCA11 s__ 6 k__Bacteria p__ c__ o__ f__ g__ s__ 5 p__Actinobacteria c__Acidimicrobiia o__Acidimicrobiales f__ g__ s__ 0 c__Actinobacteria o__Actinomycetales f__Corynebacteriaceae g__Corynebacterium s__stationis 2 f__Micrococcaceae g__Arthrobacter s__ 8 o__Bifidobacteriales f__Bifidobacteriaceae g__Bifidobacterium s__ 506 s__animalis 48 c__Coriobacteriia o__Coriobacteriales f__Coriobacteriaceae g__ s__ 734 g__Collinsella s__aerofaciens 3 

(Un CSV con los datos está disponible aquí )

Quiero trazar en un gráfico de tarta / buñuelo, donde cada círculo concéntrico es un nivel (reino, filo, etc.) y se divide de acuerdo con la sum de la columna A para ese nivel, así que termino con algo similar a esto. pero con mis datos:

tabla de uso del disco

He buscado en matplotlib y bokeh, pero lo más parecido que he encontrado hasta ahora es el ejemplo de la tabla de Donas de bokeh, que utiliza una tabla en desuso, que no sé cómo extrapolar para más de 2 niveles.

No sé si hay algo predefinido que haga esto, pero es posible construir el tuyo usando diagtwigs circulares de Groupby y superpuestas. Construí la siguiente secuencia de comandos para tomar sus datos y obtener al menos algo similar a lo que especificó.

Tenga en cuenta que las llamadas grupales (que se utilizan para calcular los totales en cada nivel) deben tener la clasificación desactivada para que las cosas se alineen correctamente. Su conjunto de datos también es muy poco uniforme, por lo que acabo de hacer algunos datos aleatorios para expandir un poco el gráfico resultante para ilustrarlo.

Probablemente tendrás que modificar los colores y las posiciones de las tags, pero puede ser un comienzo.

 import pandas as pd import matplotlib.pyplot as plt import numpy as np df = pd.read_csv('species.csv') df = df.dropna() # Drop the "no hits" line df['A'] = np.random.rand(len(df)) * 100 + 1 # Do the summing to get the values for each layer def nested_pie(df): cols = df.columns.tolist() outd = {} gb = df.groupby(cols[0], sort=False).sum() outd[0] = {'names':gb.index.values, 'values':gb.values} for lev in range(1,7): gb = df.groupby(cols[:(lev+1)], sort=False).sum() outd[lev] = {'names':gb.index.levels[lev][gb.index.labels[lev]].tolist(), 'values':gb.values} return outd outd = nested_pie(df) diff = 1/7.0 # This first pie chart fill the plot, it's the lowest level plt.pie(outd[6]['values'], labels=outd[6]['names'], labeldistance=0.9, colors=plt.style.library['bmh']['axes.color_cycle']) ax = plt.gca() # For each successive plot, change the max radius so that they overlay for i in np.arange(5,-1,-1): ax.pie(outd[i]['values'], labels=outd[i]['names'], radius=np.float(i+1)/7.0, labeldistance=((2*(i+1)-1)/14.0)/((i+1)/7.0), colors=plt.style.library['bmh']['axes.color_cycle']) ax.set_aspect('equal') 

Modulo leves cambios de la llamada a random() , esto produce una gráfica como esta: datos aleatorios de gráfico circular en capas

En tus datos reales se ve así:

datos de usuario del gráfico circular en capas