2013-03-21 17 views
8

mogę uzyskać wykres typu boxplot kolumny wynagrodzenia w DataFrame pandy ...Jak zastosować niestandardową kolejność kolumn do pandy boxplot?

train.boxplot(column='PredictionError',by='Category',sym='') 

... jednak nie mogę dowiedzieć się, jak zdefiniować indeksu zamówienie używany w kolumnie „kategoria” - I aby dostarczyć własne niestandardowe zamówienie, według innego kryterium:

category_order_by_mean_salary = train.groupby('Category')['Salary'].mean().order().keys() 

Jak mogę zastosować mój własny kolejność kolumn do boxplot kolumn? (inne niż brzydkie kludowanie nazw kolumn z prefiksem wymuszającym zamawianie)

"Kategoria" to kolumna łańcuchowa przyjmująca 27 różnych wartości: ['Accounting & Finance Jobs','Admin Jobs',...,'Travel Jobs']. Więc można go łatwo factorized z pd.Categorical.from_array()

o inspekcji, ograniczenie jest w środku pandas.tools.plotting.py:boxplot(), który przekształca obiekt kolumny nie pozwalając zamawiającego:

Przypuszczam Mógłbym albo włamać się niestandardową wersję Pandy boxplot(), lub dotrzeć do wewnętrznych części obiektu. A także zgłoś prośbę o ulepszenie.

EDYCJA: to pytanie pojawiło się w przypadku pand ~ 0.13 i prawdopodobnie zostało zastąpione przez ostatnie (0.19+?) Wersje zgodnie z późną odpowiedzią @ Cireo.

Odpowiedz

6

Trudno powiedzieć, jak to zrobić bez działającego przykładu. Moim pierwszym domysłem byłoby po prostu dodać kolumnę całkowitą z zamówieniami, które chcesz.

Prostym, brutalnym sposobem byłoby dodanie każdego pudełka po jednym na raz.

import numpy as np 
import pandas as pd 
import matplotlib.pyplot as plt 

df = pd.DataFrame(np.random.rand(37,4), columns=list('ABCD')) 
columns_my_order = ['C', 'A', 'D', 'B'] 
fig, ax = plt.subplots() 
for position, column in enumerate(columns_my_order): 
    ax.boxplot(df[column], positions=[position]) 

ax.set_xticks(range(position+1)) 
ax.set_xticklabels(columns_my_order) 
ax.set_xlim(xmin=-0.5) 
plt.show() 

enter image description here

+0

informacji Dodano dla ciebie i pomysły na obejścia. Dodanie oddzielnej wolnostojącej kolumny całkowitej nie daje przyzwoitego wykresu, ponieważ teraz twoje etykiety kolumnowe są (nieczytelne) liczbami całkowitymi, a nie tekstem. (Kludowanie prefiksu tekstowego w nazwy kategorii, aby wymusić niestandardową kolejność sortowania, jest być może najszybszym hackerem, ale wciąż brzydkim) – smci

+0

[pandas DataFrame nie może obsłużyć kategorii Categorical] (http://stackoverflow.com/questions/15356433/how-to -pogeneracja-panda-ramka-danych-kolumny-z-kategorialnej-z-kolumny-kolumny), w przeciwieństwie do R. – smci

+0

nie tam, gdzie zmierzałem. Zwykle po prostu używam 'apply' z zakodowaną tabelą odnośników. zobacz moją zredagowaną odpowiedź na inne podejście. –

1

Zauważ, że pandy mogą teraz tworzyć kategorycznych kolumn. Jeśli nie przeszkadza posiadające wszystkie kolumny obecne na wykresie, lub przycinanie je w odpowiedni sposób, można zrobić coś jak poniżej:

http://pandas.pydata.org/pandas-docs/stable/categorical.html

df['Category'] = df['Category'].astype('category', ordered=True) 

Najnowsze pandy pojawia się również, aby umożliwić positions przekazać wszystko droga od ramy do osi.

+0

Ooh, świetnie. Którą wersję dodali do tego? 0.20? – smci

+1

Link powiedział 0.15, ale byłem podejrzliwy. Nie jestem pewien, czy funkcja była w tym momencie w pełni zintegrowana. Udało mi się to wszystko zrobić w "0.19.2" – Cireo

+0

Dziękuję za sprawdzenie. – smci

1

Dodawanie osobną odpowiedź, który być może mógłby być inna kwestia - feedback mile widziane.

Chciałem dodać niestandardową kolejność kolumn w grupie, co stanowiło dla mnie wiele problemów. Koniec końców, musiałem unikać próby użycia obiektu boxplot z obiektu groupby, a zamiast tego przechodzę przez każdy wątek, aby zapewnić wyraźne pozycje.

import matplotlib.pyplot as plt 
import pandas as pd 

df = pd.DataFrame() 
df['GroupBy'] = ['g1', 'g2', 'g3', 'g4'] * 6 
df['PlotBy'] = [chr(ord('A') + i) for i in xrange(24)] 
df['SortBy'] = list(reversed(range(24))) 
df['Data'] = [i * 10 for i in xrange(24)] 

# Note that this has no effect on the boxplot 
df = df.sort_values(['GroupBy', 'SortBy']) 
for group, info in df.groupby('GroupBy'): 
    print 'Group: %r\n%s\n' % (group, info) 

# With the below, cannot use 
# - sort data beforehand (not preserved, can't access in groupby) 
# - categorical (not all present in every chart) 
# - positional (different lengths and sort orders per group) 
# df.groupby('GroupBy').boxplot(layout=(1, 5), column=['Data'], by=['PlotBy']) 

fig, axes = plt.subplots(1, df.GroupBy.nunique(), sharey=True) 
for ax, (g, d) in zip(axes, df.groupby('GroupBy')): 
    d.boxplot(column=['Data'], by=['PlotBy'], ax=ax, positions=d.index.values) 
plt.show() 

ciągu mojego ostatniego kodu, było nawet nieco bardziej zaangażowani w celu określenia pozycji, bo miałem wiele punktów danych dla każdej wartości SortBy, a skończyło się na konieczności wykonywania poniżej:

to_plot = data.sort_values([sort_col]).groupby(group_col) 
for ax, (group, group_data) in zip(axes, to_plot): 
    # Use existing sorting 
    ordering = enumerate(group_data[sort_col].unique()) 
    positions = [ind for val, ind in sorted((v, i) for (i, v) in ordering)] 
    ax = group_data.boxplot(column=[col], by=[plot_by], ax=ax, positions=positions) 
+0

Cóż, oryginalne pytanie zostało zamknięte od lat, dlaczego nie dodać nowego pytania do tej odpowiedzi? Określ pandy 0.20+ – smci

+1

Nie byłeś pewien co do etykiety wysyłania pytania, a następnie odpowiadania samemu sobie// – Cireo

+0

, to jest w porządku. Również w tym przypadku jest to pożądane - w pewnym momencie pytanie to stało się przestarzałe przez pandy 0,19 – smci

Powiązane problemy