2016-11-20 1 views
1

Donc je suis tombé sur un autre petit problème ennuyeux, comme un autre obstacle dans mes premiers pas dans l'apprentissage de Python.Colonne partagée sur les valeurs positives/négatives?

J'ai une colonne de résultat qui a des valeurs positives/négatives/nulles (gains, pertes, pas d'engagement). Je voudrais diviser en gains/pertes basées sur le signe, les zéros rempliraient les zéros et les lignes négatives dans la nouvelle colonne des gains; les zéros remplissent les zéros et les lignes positives dans les nouvelles colonnes de perte.

DONNÉES.

g=pd.DataFrame({'OUTCOME':[100,-100,400,-200,-200,-750,-250,1000,0,100,-100]},index=[1,1,2,2,2,3,3,3,4,4,4]) 

SORTIE DÉSIRÉE.

g['WINNINGS']=[100,0,400,0,0,0,0,1000,0,100,0] 
g['LOSS']=[0,100,0,200,200,750,250,0,0,0,100] 

Répondre

3

Theres pour ce faire de plus d'un de chemin, mais essentiellement ce que vous voulez faire est d'appliquer une fonction qui renvoie 0 si le nombre est inférieur ou égal à zéro, et le nombre d'entrée autrement. Et puis faites le contraire pour les pertes. Une façon est:

def winnings(value): 
    return max(value, 0) 

def losses(value): 
    return min(value, 0) 

df["winnings"] = df["outcome"].map(winnings) 
df["loss"] = = df["outcome"].map(losses) 
+0

Pouvez-vous ajouter la sortie? Pour moi, cela renvoie une erreur. – jezrael

+0

Cheers @jezrael. Je ne suis pas sûr de ce que je pensais. J'ai corrigé la réponse. – Batman

1

Vous pouvez utiliser Series.where:

df["winnings"] = df.OUTCOME.where(df.OUTCOME > 0, 0) 
df["loss"] = -1 * df.OUTCOME.where(df.OUTCOME < 0, 0) 
print (df) 
    OUTCOME winnings loss 
1  100  100  0 
1  -100   0 100 
2  400  400  0 
2  -200   0 200 
2  -200   0 200 
3  -750   0 750 
3  -250   0 250 
3  1000  1000  0 
4  0   0  0 
4  100  100  0 
4  -100   0 100 

Ou plus rapide solution avec numpy.where:

df["winnings"] = np.where(df.OUTCOME > 0, df.OUTCOME, 0) 
df["loss"] = np.where(df.OUTCOME < 0, - df.OUTCOME, 0) 

minutage:

In [68]: %timeit (jez1(df2)) 
100 loops, best of 3: 3.75 ms per loop 

In [69]: %timeit (jez(df1)) 
100 loops, best of 3: 5.82 ms per loop 

In [70]: %timeit (bat(df)) 
10 loops, best of 3: 134 ms per loop 

Code pour timings:

df=pd.DataFrame({'OUTCOME':[100,-100,400,-200,-200,-750,-250,1000,0,100,-100]},index=[1,1,2,2,2,3,3,3,4,4,4]) 
print (df) 
##[110000 rows x 1 columns] 
df = pd.concat([df]*10000).reset_index(drop=True) 
df1 = df.copy() 
df2 = df.copy() 

def winnings(value): 
    return max(value, 0) 

def losses(value): 
    return min(value, 0) 

def bat(df): 
    df["winnings"] = df.OUTCOME.apply(winnings) 
    df["loss"] = - df.OUTCOME.apply(losses) 
    return df 

def jez(df): 
    df["winnings"] = df.OUTCOME.where(df.OUTCOME > 0, 0) 
    df["loss"] = -1 * df.OUTCOME.where(df.OUTCOME < 0, 0) 
    return (df) 

def jez1(df): 
    df["winnings"] = np.where(df.OUTCOME > 0, df.OUTCOME, 0) 
    df["loss"] = np.where(df.OUTCOME < 0, - df.OUTCOME, 0) 
    return (df) 

print (bat(df)) 
print (jez(df1)) 
print (jez1(df2)) 
+0

Nice. Je n'avais pas réalisé que «où» était tellement plus performant. – Batman

+0

Oui, le mieux est d'éviter «appliquer» – jezrael