2017-06-02 3 views
8

Je voudrais produire un diagramme de dispersion de pandas DataFrame avec des étiquettes de ligne et de colonne catégoriques en utilisant matplotlib. Un exemple de DataFrame ressemble à ceci:Scatter traçant des pandas DataFrame avec des lignes/colonnes catégoriquement étiquetées

import pandas as pd 
df = pd.DataFrame({"a": [1,2], "b": [3,4]}, index=["c","d"]) 
# a b 
#c 1 2 
#d 3 4 

La taille du marqueur est la fonction des valeurs DataFrame respectives. Jusqu'à présent, je suis venu avec une solution maladroite qui énumère essentiellement les lignes et les colonnes, trace les données, et reconstitue alors les étiquettes:

flat = df.reset_index(drop=True).T.reset_index(drop=True).T.stack().reset_index() 
# level_0 level_1 0 
#0  0  0 1 
#1  0  1 2 
#2  1  0 3 
#3  1  1 4 

flat.plot(kind='scatter', x='level_0', y='level_1', s=100*flat[0]) 
plt.xticks(range(df.shape[1]), df.columns) 
plt.yticks(range(df.shape[0]), df.index) 
plt.show() 

Quel genre d'œuvres. Maintenant, question: existe-t-il une manière plus intuitive et plus intégrée de produire ce diagramme de dispersion, idéalement sans diviser les données et les métadonnées?

+0

Je ne pense pas que nous pouvons utiliser des données non numériques pour le traçage. Je vous dirai que vous devrez régler séparément les ticks ... – MaxU

+1

Je suppose que la question se traduit par * "Pourquoi aucune bibliothèque n'a-t-elle encore implémenté ma fonction de souhait de traçage personnalisé?" *. – ImportanceOfBeingErnest

Répondre

7

Peut-être pas la réponse entière vous êtes la recherche, mais une idée pour aider à gagner du temps et de la lisibilité avec la ligne de code flat=. La méthode Pandas unstack produira une série avec un MultiIndex.

dfu = df.unstack() 

print(dfu.index) 
MultiIndex(levels=[[u'a', u'b'], [u'c', u'd']], 
      labels=[[0, 0, 1, 1], [0, 1, 0, 1]]) 

Le multiindice contient contient les points x et y nécessaires pour construire le terrain (en labels). Ici, j'affecte levels et labels à des noms de variables plus informatifs mieux adaptés au traçage.

xlabels, ylabels = dfu.index.levels 
xs, ys = dfu.index.labels 

Le tracé est assez simple à partir d'ici.

plt.scatter(xs, ys, s=dfu*100) 
plt.xticks(range(len(xlabels)), xlabels) 
plt.yticks(range(len(ylabels)), ylabels) 
plt.show() 

enter image description here

J'ai essayé sur quelques différentes formes DataFrame et il semblait tenir.

4

Ce n'est pas exactement ce que vous demandez, mais il permet de visualiser les valeurs d'une manière similaire:

import seaborn as sns 

sns.heatmap(df[::-1], annot=True) 

Résultat:

enter image description here

+0

Eh bien ... C'est seaborn, pas matplotlib. Mais merci! – DyZ

3

Peut-être que vous pouvez utiliser numpy tableau et pd.melt pour créer le diagramme de dispersion comme indiqué ci-dessous:

arr = np.array([[i,j] for i in range(df.shape[1]) for j in range(df.shape[0])]) 
plt.scatter(arr[:,0],arr[:,1],s=100*pd.melt(df)['value'],marker='o') 
plt.xlabel('level_0') 
plt.ylabel('level_1') 
plt.xticks(range(df.shape[1]), df.columns) 
plt.yticks(range(df.shape[0]), df.index) 
plt.show() 

enter image description here