2015-12-02 6 views
4

Je souhaite ajouter une colonne à un pd.DataFrame dans lequel j'écris des valeurs en fonction d'une vérification dans une colonne existante.Pandas DataFrame: Ecrire des valeurs dans une colonne en fonction d'une vérification de valeur de la colonne existante

Je souhaite vérifier les valeurs dans un dictionnaire. Disons que je le dictionnaire suivant:

{"<=4":[0,4], "(4,10]":[4,10], ">10":[10,inf]} 

Maintenant, je veux vérifier dans une colonne dans mon dataframe, si les valeurs de cette colonne appartiennent à l'un des intervalles dans le dictionnaire. Si c'est le cas, je veux écrire la clé du dictionnaire correspondant à une deuxième colonne dans la même trame de données.

Ainsi, une trame de données comme:

 col_1 
    a 3 
    b 15 
    c 8 

deviendra:

 col_1 col_2 
    a 3  "<=4" 
    b 15 ">10" 
    c 8  "(4,10]" 
+0

espérons que le ci-dessous aide. –

Répondre

2

la fonction pd.cut() est utilisé pour convertir variable continue à une variable catégorique, dans ce cas, nous avons [0 , 4 , 10 , np.inf], cela signifie que nous avons 3 catégories [0 , 4], [4 , 10], [10 , inf], donc une valeur entre 0 et 4 seront affectés à la catégorie [ 0 , 4], et toute valeur entre 4 et 10 sera affectée à la catégorie [ 4 , 10 ] et ainsi de suite.

alors vous attribuer un nom pour chaque catégorie dans le même ordre, vous pouvez le faire en utilisant le paramètre d'étiquette, dans ce cas, nous avons 3 catégories [0 , 4], [4 , 10], [10 , inf], simplement nous assignerons ['<=4' , '(4,10]' , '>10'] au paramètre d'étiquette, cela signifie que la catégorie [0 , 4] sera nommée <=4, et la catégorie [4 , 10] sera nommée (4,10] et ainsi de suite.

In [83]: 
df['col_2'] = pd.cut(df.col_1 , [0 , 4 , 10 , np.inf] , labels = ['<=4' , '(4,10]' , '>10']) 
df 
Out[83]: 
    col_1 col_2 
0 3  <=4 
1 15  >10 
2 8  (4,10] 
+0

Attention à [expliquer votre solution] (http://stackoverflow.com/help/how-to-answer) un peu? –

1

Vous pouvez utiliser cette approche:

dico = pd.DataFrame({"<=4":[0,4], "(4,10]":[4,10], ">10":[10,float('inf')]}).transpose() 

foo = lambda x: dico.index[(dico[1]>x) & (dico[0]<=x)][0] 

df['col_1'].map(foo) 

#0  <=4 
#1  >10 
#2 (4,10] 
#Name: col1, dtype: object 
1

Cette solution crée une fonction nommée extract_str qui est appliquée col_1. Il utilise une compréhension de liste conditionnelle pour parcourir les clés et les valeurs du dictionnaire, en vérifiant si la valeur est supérieure ou égale à la valeur inférieure et inférieure à la valeur supérieure. Une vérification est effectuée pour s'assurer que la liste résultante ne contient pas plus d'un résultat. S'il y a une valeur dans la liste, il est retourné. Sinon, None est renvoyé par défaut.

from numpy import inf 

d = {"<=4": [0, 4], "(4,10]": [4, 10], ">10": [10, inf]} 

def extract_str(val): 
    results = [key for key, value_range in d.iteritems() 
       if value_range[0] <= val < value_range[1]] 
    if len(results) > 1: 
     raise ValueError('Multiple ranges satisfied.') 
    if results: 
     return results[0] 

df['col_2'] = df.col_1.apply(extract_str) 

>>> df 
    col_1 col_2 
a  3  <=4 
b  15  >10 
c  8 (4,10] 

Sur ce petit dataframe, cette solution est beaucoup plus rapide que la solution fournie par @ColonelBeauvel.

%timeit df['col_2'] = df.col_1.apply(extract_str) 
1000 loops, best of 3: 220 µs per loop 

%timeit df['col_2'] = df['col_1'].map(foo) 
1000 loops, best of 3: 1.46 ms per loop 
+0

Merci pour votre réponse! J'ai trouvé la réponse de @Nader Hisham à être un peu plus élégant pour la solution du problème original. Cependant, votre réponse m'a beaucoup aidé avec un autre problème en comparant les colonnes DataFrame avec des objets dict (like)! – farnold

0

Vous pouvez utiliser une fonction pour mapper. comme l'exemple. J'espère que cela peut vous aider.

import pandas as pd 
d = {'col_1':[3,15,8]} 
from numpy import inf 
test = pd.DataFrame(d,index=['a','b','c']) 
newdict = {"<=4":[0,4], "(4,10]":[4,10], ">10":[10,inf]} 

def mapDict(num): 
    print(num) 
    for key,value in newdict.items(): 
     tmp0 = value[0] 
     tmp1 = value[1] 
     if num == 0: 
      return "<=4" 
     elif (num> tmp0) & (num<=tmp1): 
      return key 

test['col_2']=test.col_1.map(mapDict) 

puis test deviendra:

col_1 col_2 
a 3 <=4 
b 15 >10 
c 8 (4,10] 

ps. Je veux savoir comment coder rapidement en débordement de pile, y a-t-il quelqu'un qui puisse me dire les trucs?