2017-06-15 12 views
0

Ich versuche, eine Funktion auf jede Zeile eines Datenrahmens anzuwenden. Der schwierige Teil ist, dass die Funktion einen neuen Datenrahmen für jede verarbeitete Zeile zurückgibt. Angenommen, die Spalten dieses Datenrahmens können leicht aus der verarbeiteten Zeile abgeleitet werden.Python: Funktion auf jede Zeile eines Pandas DataFrame anwenden und ** neuen Datenrahmen zurückgeben **

Am Ende sollte das Ergebnis alle diese Datenrahmen (1 für jede verarbeitete Zeile) verkettet sein. Ich stelle absichtlich keinen Beispielcode zur Verfügung, weil der einfachste Lösungsvorschlag ausreicht, solange der "schwierige" Teil erfüllt wird.

Ich habe Stunden damit verbracht, durch Docs und Stackoverflow zu graben, um eine Lösung zu finden. Wie immer sind die Pandas-Dokumente so praktisch, dass es neben den einfachsten Operationen, die ich einfach nicht herausfinden konnte, keine praktischen Beispiele gibt. Ich habe auch darauf geachtet, keine doppelten Fragen zu verpassen. Danke vielmals.

+0

Warum müssen Sie einen Datenrahmen zurückgeben, wenn Sie sie am Ende nur verketten? Nichts in Ihrer Frage erklärt, warum diese "Anforderung" relevant ist. Tatsächlich verarbeiten Sie die Daten wahrscheinlich ineffizient, wenn Sie in Zeilen anstelle von Spalten denken. – Alexander

+0

... haben Sie die Methode 'pd.DataFrame.apply' versucht? Es scheint genau zu tun * was du willst. –

+0

@Alexander Ich brauche diese Anforderung tatsächlich. Betrachten Sie dieses zusammengesetzte Beispiel: Jede Zeile in der Datentabelle ist der Vorname einer Person. Die auf jede Zeile anzuwendende Funktion wird diesen Namen annehmen und durch jede Logik (die auf externe Objekte/Datenrahmen verweist) werden 5 numerische Merkmale zurückgegeben, die mit dem Namen verbunden sind. Jetzt brauche ich den Namen und seine 5 Merkmale im DataFrame-Format, d. H. 5 Zeilen mit 2 Spalten: Name | Feature Und das gleiche gilt für alle Zeilen. –

Antwort

0

Vorausgesetzt, dass die Funktion, die Sie jede Zeile anwenden wird f genannt

pd.concat({i: f(row) for i, row in df.iterrows()}) 

Arbeitsbeispiel

df = pd.DataFrame(np.arange(25).reshape(5, 5), columns=list('ABCDE')) 

def f(row): 
    return pd.concat([row] * 2, keys=['x', 'y']).unstack().drop('C', 1).assign(S=99) 

pd.concat({i: f(row) for i, row in df.iterrows()}) 

     A B D E S 
0 x 0 1 3 4 99 
    y 0 1 3 4 99 
1 x 5 6 8 9 99 
    y 5 6 8 9 99 
2 x 10 11 13 14 99 
    y 10 11 13 14 99 
3 x 15 16 18 19 99 
    y 15 16 18 19 99 
4 x 20 21 23 24 99 
    y 20 21 23 24 99 

Oder

df.groupby(level=0).apply(lambda x: f(x.squeeze())) 


     A B D E S 
0 x 0 1 3 4 99 
    y 0 1 3 4 99 
1 x 5 6 8 9 99 
    y 5 6 8 9 99 
2 x 10 11 13 14 99 
    y 10 11 13 14 99 
3 x 15 16 18 19 99 
    y 15 16 18 19 99 
4 x 20 21 23 24 99 
    y 20 21 23 24 99 
0

ich es auf diese Weise tun würde - obwohl ich fest, die .apply ist möglicherweise, was Sie suchen.

import pandas as pd 
import numpy as np 

np.random.seed(7) 

orig=pd.DataFrame(np.random.rand(6,3)) 

orig.columns=(['F1','F2','F3']) 

res=[] 


for i,r in orig.iterrows(): 
    tot=0 
    for col in r: 
     tot=tot+col 
    rv={'res':tot} 
    a=pd.DataFrame.from_dict(rv,orient='index',dtype=np.float64) 
    res.append(a) 


res[0].head() 

Sollte so etwas wie dieses

{'res':10} 
0

zurückkehren Es ist unklar, was Sie erreichen wollen, aber ich bezweifle, dass Sie getrennte Datenrahmen erstellen müssen.

Das folgende Beispiel zeigt, wie Sie einen Datenframe verwenden, ihn in die entsprechenden Spalten unterteilen, eine Funktion foo auf eine der Spalten anwenden und dann eine zweite Funktion bar anwenden, die mehrere Werte zurückgibt.

df = pd.DataFrame({ 
    'first_name': ['john', 'nancy', 'jolly'], 
    'last_name': ['smith', 'drew', 'rogers'], 
    'A': [1, 4, 7], 
    'B': [2, 5, 8], 
    'C': [3, 6, 9] 
}) 

>>> df 
first_name last_name A B C 
0 john smith 1 2 3 
1 nancy drew 4 5 6 
2 jolly rogers 7 8 9 

def foo(first_name): 
    return 2 if first_name.startswith('j') else 1 

def bar(first_name): 
    return (2, 0) if first_name.startswith('j') else (1, 3) 

columns_of_interest = ['first_name', 'A'] 

df_new = pd.concat([ 
    df[columns_of_interest].assign(x=df.first_name.apply(foo)), 
    df.first_name.apply(bar).apply(pd.Series)], axis=1) 

>>> df_new 
first_name A x 0 1 
0 john 1 2 2 0 
1 nancy 4 1 1 3 
2 jolly 7 2 2 0 
Verwandte Themen