2015-04-28 7 views
8

Ich habe Gleitkommadaten in einem Pandas Datenrahmen. Jede Spalte repräsentiert eine Variable (sie haben String-Namen) und jede Zeile eine Menge von Werten (die Zeilen haben Integer-Namen, die nicht wichtig sind).Willst du Pandas Dataframe als Multiple Histogramme mit log10 skalieren X-Achse

>>> print data 
0  kppawr23 kppaspyd 
1  3.312387 13.266040 
2  2.775202 0.100000 
3 100.000000 100.000000 
4 100.000000 39.437420 
5  17.017150 33.019040 
... 

Ich möchte für jede Spalte ein Histogramm zeichnen. Das beste Ergebnis, das ich erreicht habe, ist mit der hist Methode des Datenrahmen:

data.hist(bins=20) 

aber ich mag, dass die x-Achse jeden Histogramm auf log10 Maßstab sein. Und die Bins müssen ebenfalls log10 sein, aber das ist einfach genug mit bins = np.logspace (-2,2,20).

Eine Abhilfe könnte sein, um die Daten zu log10-Transformation vor dem Plotten, aber die Ansätze, die ich habe versucht,

data.apply(math.log10) 

und

data.apply(lambda x: math.log10(x)) 

geben Sie mir einen Floating-Point-Fehler.

"cannot convert the series to {0}".format(str(converter))) 
TypeError: ("cannot convert the series to <type 'float'>", u'occurred at index kppawr23') 

Antwort

5

könnten Sie

verwenden
ax.set_xscale('log') 

data.hist() eine Reihe von Achsen zurückgibt. Sie müssen für jede Achse ax.set_xscale('log') aufrufen, ax, um jede der logarithmischen skaliert zu machen.


Zum Beispiel

import numpy as np 
import pandas as pd 
import matplotlib.pyplot as plt 
np.random.seed(2015) 

N = 100 
arr = np.random.random((N,2)) * np.logspace(-2,2,N)[:, np.newaxis] 
data = pd.DataFrame(arr, columns=['kppawr23', 'kppaspyd']) 

bins = np.logspace(-2,2,20) 
axs = data.hist(bins=bins) 
for ax in axs.ravel(): 
    ax.set_xscale('log') 

plt.gcf().tight_layout() 
plt.show() 

enter image description here


Durch die Art und Weise ergibt, das Protokoll eines jeden Wertes in dem Datenrahmen verwenden data, nehmen könnten Sie

weil NumPy ufuncs (wie np.log10) kann auf Pandas DataFrames angewendet werden, weil sie elementwise on all the values in the DataFrame arbeiten.

data.apply(math.log10) hat nicht funktioniert, weil apply versucht, eine ganze Spalte (eine Reihe) von Werten zu math.log10 zu übergeben. math.log10 erwartet nur einen skalaren Wert.

data.apply(lambda x: math.log10(x)) schlägt aus dem gleichen Grund fehl, die data.apply(math.log10) tut. Außerdem, wenn data.apply(func) und data.apply(lambda x: func(x)) beide brauchbare Optionen waren, sollte die erste bevorzugt werden, da die Lambda-Funktion den Aufruf nur etwas langsamer machen würde.

könnten Sie data.apply(np.log10) verwenden, wieder, da die NumPy ufunc np.log10 kann Serie angewendet werden, aber es gibt keinen Grund, dies zu tun, wenn np.log10(data) Arbeiten zu stören.

Sie auch data.applymap(math.log10) seit applymap Anrufe math.log10 auf jeden Wert in data one-at-a-time benutzen konnten. Aber das wäre viel langsamer als Aufruf der entsprechenden NumPy Funktion, np.log10 auf dem gesamten DataFrame. Dennoch ist es wert, über applymap zu wissen, falls Sie einige benutzerdefinierte Funktion aufrufen müssen, die kein ufunc ist.

+0

Danke! Ich wusste nichts über Ravel(). Ich habe mich auch nicht mit dem Thema beschäftigt. Ich habe versucht, mich auf Pandas zu konzentrieren, weil es extrem schnell beim Lesen großer Datensätze ist. –

+0

Übrigens, gibt es irgendeine Möglichkeit, es zu beschleunigen? Ich habe 219 Histogramme zu produzieren und es dauert Minuten (läuft im Debug-Modus in PyCharm Community Edition). –

+0

Und kann ich Tight_layout irgendwie auf data.hist anwenden? –