2017-08-01 2 views
1

avec exemple ci-dessous:pandas géants dataframe appliquer à l'aide des arguments supplémentaires

df = pd.DataFrame({'signal':[1,0,0,1,0,0,0,0,1,0,0,1,0,0],'product':['A','A','A','A','A','A','A','B','B','B','B','B','B','B'],'price':[1,2,3,4,5,6,7,1,2,3,4,5,6,7],'price2':[1,2,1,2,1,2,1,2,1,2,1,2,1,2]}) 

J'ai une fonction « fill_price » pour créer une nouvelle colonne « Price_B » basée sur « signal » et « prix ». Price_B est égal à Price si «signal» est 1. Price_B est égal à Price_B de la rangée précédente si le signal est 0. Si le sous-groupe commence par un «signal» 0, alors «price_B» sera maintenu à 0 jusqu'à ' signal » tourne 1.

Actuellement, j'ai:

def fill_price(df, signal,price_A): 
p = df[price_A].where(df[signal] == 1) 
return p.ffill().fillna(0).astype(df[price_A].dtype) 

c'est ensuite appliquée à l'aide:

df['Price_B'] = fill_price(df,'signal','price') 

Cependant, je veux utiliser df.groupby. ('produit') appliquer () pour appliquer cette fonction fill_price à deux sous-ensembles de colonnes 'product' séparément, et l'appliquer aussi bien à 'price' qu'à 'price' colonnes price2 '. Quelqu'un pourrait-il aider avec ça?

Je veux essentiellement faire:

df.groupby('product',groupby_keys=False).apply(fill_price, 'signal','price2') 
+0

Est-ce que cela fonctionne? 'df.groupby ('product'). apply (lambda x: fill_price (x, 'signal', 'prix'))' –

Répondre

1

IIUC, vous pouvez utiliser cette syntaxe:

df['Price_B'] = df.groupby('product').apply(lambda x: fill_price(x,'signal','price2')).reset_index(level=0, drop=True) 

Sortie:

price price2 product signal Price_B 
0  1  1  A  1  1 
1  2  2  A  0  1 
2  3  1  A  0  1 
3  4  2  A  1  2 
4  5  1  A  0  2 
5  6  2  A  0  2 
6  7  1  A  0  2 
7  1  2  B  0  0 
8  2  1  B  1  1 
9  3  2  B  0  1 
10  4  1  B  0  1 
11  5  2  B  1  2 
12  6  1  B  0  2 
13  7  2  B  0  2 

Vous pouvez écrire autant plus simple sans supplément fonction.

df['Price_B'] = (df.groupby('product',as_index=False) 
        .apply(lambda x: x['price2'].where(x.signal==1).ffill().fillna(0)) 
        .reset_index(level=0, drop=True)) 
+0

Cela fonctionne. Je suis un peu confus cependant, comme 1. pourquoi avons-nous réinitialiser l'index à la fin 2. la fonction s'applique à une base de données, mais dans la fonction lambda nous alimentons les lignes à travers elle? Merci –

+0

C'est la façon dont votre fonction est construite, vous renvoyez une base de données avec un index, puis groupby met un nouvel index du groupe. Oui, votre fonction prend un dataframe comme premier argument, dans la fonction lambda, nous passons juste quelques lignes "groupées" de la dataframe à votre fonction et elle retourne une dataframe que nous effaçons ensuite l'index de glissement et laissons aligner les Pandas votre fichier de données original avec l'image de données modfied basé sur l'index original. –

+0

@PrintableBao Voir mise à jour où j'ai réécrit en pure fonction lambda sans l'appel de fonction supplémentaire. –