2015-03-27 11 views
5

Mam następujący ramkę danych:Zastosuj funkcję wiersz mądry na ramce danych Pandy na kolumnach z wartościami liczbowymi

import pandas as pd 
df = pd.DataFrame({'AAA' : ['w','x','y','z'], 'BBB' : [10,20,30,40],'CCC' : [100,50,-30,-50]}) 

który wygląda tak:

In [32]: df 
Out[32]: 
    AAA BBB CCC 
0 w 10 100 
1 x 20 50 
2 y 30 -30 
3 z 40 -50 

Co chcę zrobić, to wykonać działanie funkcji w każdym wierszu dla każdej kolumny, z wyjątkiem tych o wartości nie liczbowej (w tym przypadku AAA). W rzeczywistym przypadku przypadek nie numeryczny jest zawsze w pierwszej kolumnie, a reszta (może być większa niż 2 kolumny) jest zawsze numeryczna.

Ostateczna pożądane wyjście jest:

AAA BBB CCC Score 
0 w 10 100 110 
1 x 20 50 70 
2 y 30 -30 0 
3 z 40 -50 -10 

próbowałem tego, ale nie powiodło się:

import numpy as np 
df["Score"] = df.apply(np.sum, axis=1) 

Jaki jest właściwy sposób to zrobić?

Update2:

Jest to kod, który daje SettingWithCopyWarning. Świeżo rozpoczynaj ipython do testowania.

import pandas as pd 
import numpy as np 
def cvscore(fclist): 
    sd = np.std(fclist) 
    mean = np.mean(fclist) 
    cv = sd/mean 
    return cv 

def calc_cvscore_on_df(df): 
    df["CV"] = df.iloc[:,1:].apply(cvscore, axis=1) 
    return df 

df3 = pd.DataFrame(np.random.randn(1000, 3), columns=['a', 'b', 'c']) 
calc_cvscore_on_df(df3[["a","b"]]) 

Odpowiedz

12

Aby zaznaczyć wszystko oprócz pierwszej kolumnie, można użyć df.iloc[:, 1:]:

In [371]: df['Score'] = df.iloc[:, 1:].sum(axis=1) 

In [372]: df 
Out[372]: 
    AAA BBB CCC Score 
0 w 10 100 110 
1 x 20 50  70 
2 y 30 -30  0 
3 z 40 -50 -10 

Aby zastosować dowolną funkcję, func, do każdego wiersza:

df.iloc[:, 1:].apply(func, axis=1) 

Dla przykład:

import numpy as np 
import pandas as pd 

def cvscore(fclist): 
    sd = np.std(fclist) 
    mean = np.mean(fclist) 
    cv = sd/mean 
    return cv 

df = pd.DataFrame({'AAA' : ['w','x','y','z'], 'BBB' : [10,20,30,40], 
        'CCC' : [100,50,-30,-50]}) 

df['Score'] = df.iloc[:, 1:].apply(cvscore, axis=1) 
print(df) 

daje

AAA BBB CCC  Score 
0 w 10 100 1.211386 
1 x 20 50 0.868377 
2 y 30 -30  NaN 
3 z 40 -50 -5.809058 
+1

Grumble. Czy znasz lepszy sposób obsługi ogólnego przypadku (gdzie nie koniecznie wiemy, które kolumny są numeryczne wcześniej) niż 'df.select_dtypes (include = [np.number]) .sum (axis = 1)'? – DSM

+0

@unutbu: Jak mogę to uogólnić dla ogólnej funkcji. W rzeczywistości nie jest to "np.sum", ale moja inna specyficzna funkcja. Zobacz aktualizację. – pdubois

+0

@DSM: 'df.select_dtypes (include = [np.number]) .sum (axis = 1)' wydaje się najlepszą odpowiedzią. Co ci się nie podoba w tym stylu? – unutbu

Powiązane problemy