2016-10-05 3 views
3

Ich habe Daten prognostiziert, die ich nach Monat gruppiert. Die ursprüngliche Datenrahmen etwas wie folgt aus:Pandas reorder Teilmenge von Spalten aus einem gruppierten Datenrahmen

>>clean_table_grouped[0:5] 
     STYLE COLOR SIZE FOR 
MONTH       01/17 10/16 11/16 12/16 
    0 ####### ###### #### 0.0  15.0 15.0  15.0 
    1 ####### ###### #### 0.0  15.0 15.0  15.0 
    2 ####### ###### #### 0.0  15.0 15.0  15.0 
    3 ####### ###### #### 0.0  15.0 15.0  15.0 
    4 ####### ###### #### 0.0  15.0 15.0  15.0 

>>clean_table_grouped.ix[0:,"FOR"][0:5] 
MONTH 01/17 10/16 11/16 12/16 
0  0.0 15.0 15.0 15.0 
1  0.0 15.0 15.0 15.0 
2  0.0 15.0 15.0 15.0 
3  0.0 15.0 15.0 15.0 
4  0.0 15.0 15.0 15.0 

Ich will einfach diese 4 Spalten in der Folge Art und Weise neu ordnen:

(wobei der Rest der Datenrahmen unberührt)

MONTH 10/16 11/16 12/16 01/17 
0  15.0 15.0 15.0 0.0 
1  15.0 15.0 15.0 0.0 
2  15.0 15.0 15.0 0.0 
3  15.0 15.0 15.0 0.0 
4  15.0 15.0 15.0 0.0 

Meine Die versuchte Lösung bestand darin, die Spalten der Teilmenge neu zu ordnen, die dem folgenden Post folgte: How to change the order of DataFrame columns?

Ich ging davon durch die Spaltenliste greifen und es erste

>>for_cols = clean_table_grouped.ix[:,"FOR"].columns.tolist() 
>>for_cols.sort(key = lambda x: x[0:2]) #sort by month ascending 
>>for_cols.sort(key = lambda x: x[-2:]) #then sort by year ascending 

Abfrage der Datenrahmen Sortierung funktioniert gut

>>clean_table_grouped.ix[0:,"FOR"][for_cols] 
MONTH 10/16 11/16 12/16 01/17 
0  15.0 15.0 15.0 0.0 
1  15.0 15.0 15.0 0.0 
2  15.0 15.0 15.0 0.0 
3  15.0 15.0 15.0 0.0 
4  15.0 15.0 15.0 0.0 

Allerdings, wenn ich versuche, Werte in der ursprünglichen Tabelle zu setzen, ich erhalten eine Tabelle von "NaN":

>>clean_table_grouped.ix[0:,"FOR"] = clean_table_grouped.ix[0:,"FOR"][for_cols] 
>>clean_table_grouped.ix[0:,"FOR"] 
MONTH 01/17 10/16 11/16 12/16 
0  NaN NaN NaN NaN 
1  NaN NaN NaN NaN 
2  NaN NaN NaN NaN 
3  NaN NaN NaN NaN 
4  NaN NaN NaN NaN 
5  NaN NaN NaN NaN 

ich auch gekettet Syntax zu vermeiden versucht haben, zippen (.IX [] []). Dies vermeidet die NaN, ist es jedoch nicht die Datenrahmen ändert -__-

>>for_cols = zip(["FOR", "FOR", "FOR", "FOR"], for_cols) 
>>clean_table_grouped.ix[0:,"FOR"] = clean_table_grouped.ix[0:,for_cols] 
>>clean_table_grouped.ix[0:,"FOR"] 
MONTH 01/17 10/16 11/16 12/16 
0  0.0 15.0 15.0 15.0 
1  0.0 15.0 15.0 15.0 
2  0.0 15.0 15.0 15.0 
3  0.0 15.0 15.0 15.0 
4  0.0 15.0 15.0 15.0 

Ich weiß, ich bin mit ix Werte neu zuzuweisen. Allerdings habe ich diese Technik in der Vergangenheit auf Datenrahmen verwendet, die nicht gruppiert sind, und es hat gut funktioniert.

Wenn diese Frage bereits in einem anderen Beitrag (in einer klaren Weise) beantwortet wurde, bitte den Link angeben. Ich suchte, konnte aber nichts Ähnliches finden.

EDIT: Ich habe eine Lösung gefunden. Manuelles Neuindizieren durch Erstellen eines neuen Multiindex-Datenrahmens in der Reihenfolge, in der die Spalten sortiert werden sollen. Ich habe die folgende Lösung veröffentlicht.

+0

Wie ist die Struktur Ihres ursprünglichen DataFrame? –

Antwort

0

war meine eigene Lösung basierend auf der zweiten Antwort des unten Beitrag: How can I reorder multi-indexed dataframe columns at a specific level

Ziemlich viel ... gerade einen neuen Datenrahmen mit dem Multiindex erstellen Sie wollen. Der Versuch, Werte mit .ix, .loc, .iloc einzufügen, wird bei multiindexierten Datenrahmen nicht gut unterstützt. Wenn Sie die Werte der Teilmenge der Spalten vollständig ändern möchten (nicht nur tauschen), ist die Lösung von Nickil, die Tabellen zu trennen und neu zu verbinden, definitiv der richtige Weg. Wenn Sie jedoch nur versuchen, die Spalten zu tauschen, funktioniert das unten völlig einwandfrei. Ich wählte dies als die Antwort über Nickil Lösung, weil diese Lösung besser für mich arbeitete, da ich andere Daten neben "FOR" nach Monat gruppiert hatte und es gab mir mehr Flexibilität bei der Neuordnung der Spalten.

Zuerst speichern Sie die Listen in der ORDER SIE WÜNSCHEN:

>>reindex_list = ['STYLE','COLOR','SIZE','FOR'] #desired order 
>>month_list = clean_table_grouped.ix[0:,"FOR"].columns.tolist() 
>>month_list.sort(key = lambda x: x[0:2]) #sort by month ascending 
>>month_list.sort(key = lambda x: x[-2:]) #sort by year ascending 

Dann ein börsennotiertes schaffen Reißverschluss, wo Stil, Farbe, Größe mit Reißverschluss lassen ‚‘, und ‚FOR‘ wird mit jedem Monat gezippt. Wie so:

[('STYLE',''),('COLOR',''),..., ('FOR','10/16'), ('FOR','11/16'), ...] 

Hier ist ein Algorithmus, der es automatisch tut:

>>zip_list = [] 
>> 
for i in reindex_list: 
if i in ['FOR']: 
    for j in month_list: 
     if j != '': 
      zip_list.append(zip([i],[j])[0]) 
else: 
    zip_list.append(zip([i],[''])[0]) 

Dann erstellen Sie einen Multi-Index aus der Tupel Liste, die Sie gerade Reißverschluss:

>>multi_cols = pd.MultiIndex.from_tuples(zip_list, names=['','MONTH']) 

Und schließlich schaffen ein neuer Datenrahmen vom alten mit dem neuen Multiindex:

>>clean_table_grouped_ordered = pd.DataFrame(clean_table_grouped, columns=multi_cols) 
>>clean_table_grouped_ordered[0:5] 
     STYLE COLOR SIZE FOR 
MONTH     10/16 11/16 12/16 01/17 
     #### #### ### 15.0 15.0 15.0 0.0 
     #### #### ### 15.0 15.0 15.0 0.0 
     #### #### ### 15.0 15.0 15.0 0.0 
     #### #### ### 15.0 15.0 15.0 0.0 
     #### #### ### 15.0 15.0 15.0 0.0 
     #### #### ### 15.0 15.0 15.0 0.0 
1

sortieren Spaltennamen Datum Zeichenketten enthalten und später als Teilmenge verwenden, um die Spalten in dieser bestimmten Reihenfolge zurückzukehren:

from datetime import datetime 
df[sorted(df.columns, key=lambda x: datetime.strptime(x, '%m/%y'))] 

Image


Toy Daten:

from datetime import datetime 
np.random.seed(42) 

cols = [['STYLE', 'COLOR', 'SIZE', 'FOR', 'FOR', 'FOR', 'FOR'], 
     ['', '', '', '01/17', '10/16', '11/16', '12/16']] 
tups = list(zip(*cols)) 
index = pd.MultiIndex.from_tuples(tups, names=[None, 'MONTH']) 
clean_table_grouped = pd.DataFrame(np.random.randint(0, 100, (100, 7)), 
            index=np.arange(100), columns=index) 
clean_table_grouped = clean_table_grouped.head() 
clean_table_grouped 

Image

Split der Multi-Index DF in zwei mit dem man die Prognosewerte und die andere die restlichen DF enthält.

for_df = clean_table_grouped[['FOR']] 
clean_table_grouped = clean_table_grouped.drop(['FOR'], axis=1, level=0) 

Prognose DF:

for_df 

Image

Rest DF:

clean_table_grouped 

Image

Sortieren der Spalten in der Prognose DF durch Anwenden des gleichen Verfahrens wie im vorbearbeiteten Post.

order = sorted(for_df['FOR'].columns.tolist(), key=lambda x: datetime.strptime(x, '%m/%y')) 

Making the DF in der gleichen Reihenfolge durch die sortierte list von Spalten subsetting.

for_df = for_df['FOR'][order] 

Concatenate die Prognose DF mit sich selbst ein Multi-Index wie Spalte zu erstellen.

for_df = pd.concat([for_df, for_df], axis=1, keys=['FOR']) 

Schließlich, verbinden Sie sie auf dem gemeinsamen Index.

clean_table_grouped.join(for_df) 

Image

+0

Dies funktioniert, um die Reihenfolge der Spalten in der * Teilmenge * des Datenrahmens zu vertauschen, und es ist eine elegantere Lösung, die Spaltenreihenfolge als meine eigene zu vertauschen. Mein Problem bestand jedoch darin, diese getauschte Reihenfolge IN den ursprünglichen Datenrahmen zu ersetzen, ohne die anderen Spalten (Stil, Farbe, Größe) zu beeinflussen. Da ich die ursprüngliche Struktur des Datenrahmens, in dem ich aktualisieren wollte, nicht bereitgestellt habe, habe ich diese Antwort nicht abgegeben. Vielen Dank! – xdzzz

+0

Hab 'das. Jetzt, wo ich weiß, was Sie gefragt haben, nachdem Sie Ihren Start 'DF' bereitgestellt haben, habe ich einen ähnlichen' DF' nachgebildet, um Ihnen die gewünschte Ausgabe zu geben, nach der Sie gesucht haben. * Siehe Bearbeiten * –

+0

Nickil, gelöst, mein Freund, gelöst. Gut gespielt. Ich muss sagen, ich habe nicht mit solch einer verworrenen Lösung gerechnet. Ihre Lösung funktioniert jedoch einwandfrei :). Ich möchte darauf hinweisen, dass ich neben "FOR" noch andere gruppierte Daten hatte; Der Join hängt die for_df-Tabelle an das Ende der ursprünglichen Tabelle an, aber das ist nicht wirklich ein Problem. Es tauscht die "FOR" -Spalten entsprechend aus und verbindet sie nahtlos mit der ursprünglichen Tabelle. – xdzzz

Verwandte Themen