2017-03-07 3 views
2

J'ai deux dataframes, disons df et map_dum. Voici le df.Pandas alternative d'ajouter une nouvelle colonne avec beaucoup de conditions autres que d'appliquer

>>> print(df) 
    sales 
0  5 
1  10 
2  9 
3  7 
4  1 
5  1 
6  -1 
7  2 
8  9 
9  8 
10  1 
11  3 
12  10 
13  -2 
14  8 
15  5 
16  9 
17  6 
18  10 
19  -1 
20  5 
21  3 

Et voici pour le map_dum.

>>> print(map_dum) 
    class more_than_or_equal_to less_than 
0  -1     -1000   0 
1  1      0   2 
2  2      2   4 
3  3      4   6 
4  4      6   8 
5  5      8   10 
6  6      10  1000 

Mon but est d'ajouter une nouvelle colonne à la df, colonne class. Pour ce faire, je dois vérifier que la valeur df['sales'] se situe entre les valeurs de map_dum. Par exemple si je veux savoir le class pour la première rangée dans df['sales'], 5, alors le class serait 3. La sortie finale aimerait ci-dessous.

>>> print(df) 
    sales class 
0  5  3 
1  10  6 
2  9  5 
3  7  4 
4  1  1 
5  1  1 
6  -1  -1 
7  2  2 
8  9  5 
9  8  5 
10  1  1 
11  3  2 
12  10  6 
13  -2  -1 
14  8  5 
15  5  3 
16  9  5 
17  6  4 
18  10  6 
19  -1  -1 
20  5  3 
21  3  2 

Actuellement, je suis en utilisant apply pour résoudre ce problème, mais il est très lent depuis mon ensemble de données est assez énorme.

def add_class(sales, mapping, lower_limit, upper_limit): 
    result = mapping.loc[((mapping[lower_limit]<=sales)&(mapping[upper_limit]>sales)), 'class'].tolist()[0] 
    return result 

df['class'] = df['sales'].apply(lambda sales: add_class(sales, map_dum, 'more_than_or_equal_to', 'less_than')) 

Par conséquent, les performances sont importantes dans mon cas. Toute autre façon d'ajouter la colonne class au df sans violer les critères, quelque chose comme la solution de vectorisation? Merci pour toute aide!

Répondre

3

Je pense que vous avez besoin cut:

bins = [-1000, 0, 2, 4, 6, 8, 10, 1000] 
labels=[-1,1,2,3,4,5,6] 
df['class'] = pd.cut(df['sales'], bins=bins, labels=labels, right=False) 
print (df) 
    sales class 
0  5  3 
1  10  6 
2  9  5 
3  7  4 
4  1  1 
5  1  1 
6  -1 -1 
7  2  2 
8  9  5 
9  8  5 
10  1  1 
11  3  2 
12  10  6 
13  -2 -1 
14  8  5 
15  5  3 
16  9  5 
17  6  4 
18  10  6 
19  -1 -1 
20  5  3 
21  3  2 

Pour les valeurs add dynamiques de map_dum utilisation:

bins = [map_dum['more_than_or_equal_to'].iat[0]] + map_dum['less_than'].tolist() 
labels= map_dum['class'] 
df['class'] = pd.cut(df['sales'], bins=bins, labels=labels, right=False) 
print (df) 
+0

Merci beaucoup! C'est en effet plus rapide et plus propre! – arnold