web-dev-qa-db-fra.com

Comparez deux colonnes avec des pandas

En utilisant ceci comme point de départ:

a = [['10', '1.2', '4.2'], ['15', '70', '0.03'], ['8', '5', '0']]
df = pd.DataFrame(a, columns=['one', 'two', 'three'])

Out[8]: 
  one  two three
0   10  1.2   4.2
1   15  70   0.03
2    8   5     0

Je veux utiliser quelque chose comme une déclaration if au sein des pandas. 

if df['one'] >= df['two'] and df['one'] <= df['three']:
    df['que'] = df['one']

Fondamentalement, vérifiez chaque ligne via l'instruction if, créez une nouvelle colonne. 

Les docs disent d'utiliser .all mais il n'y a pas d'exemple ...

36
Merlin

Vous pouvez utiliser np.where . Si cond est un tableau booléen et que A et B sont des tableaux, alors

C = np.where(cond, A, B)

définit C comme étant égal à Acond est vrai, et Bcond est faux.

import numpy as np
import pandas as pd

a = [['10', '1.2', '4.2'], ['15', '70', '0.03'], ['8', '5', '0']]
df = pd.DataFrame(a, columns=['one', 'two', 'three'])

df['que'] = np.where((df['one'] >= df['two']) & (df['one'] <= df['three'])
                     , df['one'], np.nan)

les rendements

  one  two three  que
0  10  1.2   4.2   10
1  15   70  0.03  NaN
2   8    5     0  NaN

Si vous avez plusieurs conditions, vous pouvez utiliser np.select à la place de . Par exemple, si vous souhaitez que df['que'] soit égal à df['two'] lorsque df['one'] < df['two'], alors

conditions = [
    (df['one'] >= df['two']) & (df['one'] <= df['three']), 
    df['one'] < df['two']]

choices = [df['one'], df['two']]

df['que'] = np.select(conditions, choices, default=np.nan)

les rendements

  one  two three  que
0  10  1.2   4.2   10
1  15   70  0.03   70
2   8    5     0  NaN

Si nous pouvons supposer que df['one'] >= df['two'] lorsque df['one'] < df['two'] est égal à False, les conditions et les choix pourraient alors être simplifiés.

conditions = [
    df['one'] < df['two'],
    df['one'] <= df['three']]

choices = [df['two'], df['one']]

(L'hypothèse peut ne pas être vraie si df['one'] ou df['two'] contient des NaN.)


Notez que 

a = [['10', '1.2', '4.2'], ['15', '70', '0.03'], ['8', '5', '0']]
df = pd.DataFrame(a, columns=['one', 'two', 'three'])

définit un DataFrame avec des valeurs de chaîne. Comme elles ont l’air numérique, vous feriez bien de convertir ces chaînes en floats:

df2 = df.astype(float)

Cela change cependant les résultats, puisque les chaînes comparent caractère par caractère, tandis que les flottants sont comparés numériquement.

In [61]: '10' <= '4.2'
Out[61]: True

In [62]: 10 <= 4.2
Out[62]: False
55
unutbu

Vous pouvez utiliser .equals pour des colonnes ou des images complètes.

df['col1'].equals(df['col2'])

Si elles sont égales, cette instruction retournera True, sinon False.

30
ccook5760

Vous pouvez utiliser apply () et faire quelque chose comme ça

df['que'] = df.apply(lambda x : x['one'] if x['one'] >= x['two'] and x['one'] <= x['three'] else "", axis=1)

ou si vous préférez ne pas utiliser de lambda 

def que(x):
    if x['one'] >= x['two'] and x['one'] <= x['three']:
        return x['one']
    else:
        ''
df['que'] = df.apply(que, axis=1)
19
Bob Haffner

Une solution consiste à utiliser une série booléenne pour indexer la colonne df['one']. Cela vous donne une nouvelle colonne où les entrées True ont la même valeur que la même ligne que df['one'] et les valeurs False sont NaN.

La série booléenne est simplement donnée par votre instruction if (bien qu'il soit nécessaire d'utiliser & au lieu de and):

>>> df['que'] = df['one'][(df['one'] >= df['two']) & (df['one'] <= df['three'])]
>>> df
    one two three   que
0   10  1.2 4.2      10
1   15  70  0.03    NaN
2   8   5   0       NaN

Si vous souhaitez que les valeurs NaN soient remplacées par d'autres valeurs, vous pouvez utiliser la méthode fillna sur la nouvelle colonne que. J'ai utilisé 0 au lieu de la chaîne vide ici:

>>> df['que'] = df['que'].fillna(0)
>>> df
    one two three   que
0   10  1.2   4.2    10
1   15   70  0.03     0
2    8    5     0     0
8
Alex Riley

Placez chaque condition entre parenthèses, puis utilisez l'opérateur & pour combiner les conditions:

df.loc[(df['one'] >= df['two']) & (df['one'] <= df['three']), 'que'] = df['one']

Vous pouvez remplir les lignes qui ne correspondent pas en utilisant simplement ~ (l'opérateur "not") pour inverser la correspondance:

df.loc[~ ((df['one'] >= df['two']) & (df['one'] <= df['three'])), 'que'] = ''

Vous devez utiliser & et ~ plutôt que and et not car les opérateurs & et ~ fonctionnent élément par élément.

Le résultat final:

df
Out[8]: 
  one  two three que
0  10  1.2   4.2  10
1  15   70  0.03    
2   8    5     0  
4
Marius

Je pense que l'intuition la plus proche de l'OP est une déclaration inline si:

df['que'] = (df['one'] if ((df['one'] >= df['two']) and (df['one'] <= df['three'])) 
0
Nic Scozzaro