J'ai un dataframe avec 6 colonnes J'ai besoin de comparer chaque 3 colonnes avec les trois autres colonnes une autre. Les 6 colonnes sont les mêmes données mais les valeurs des 3 premières proviennent d'une méthode et les trois autres sont d'une autre méthode. J'ai donc besoin de les comparer pour les différences ou les variations.

Df.head()

  A    B    C  A-1  B-1  C-1
190  289  300  190  287  267

Et mes conditions sont,

conditions = [(combined_min['A'] == combined_min['A-1']) & (combined_min['B'] == combined_min['B-1'] & combined_min['C'] == combined_min['C-1']),
              (combined_min['A'] > combined_min['A-1']) & (combined_min['B'] > combined_min['B-1'] & combined_min['C'] > combined_min['C-1']),
              (combined_min['A'] < combined_min['A-1']) & (combined_min['B'] < combined_min['B-1'] & combined_min['C'] < combined_min['C-1'])]

Et mes choix sont,

choices     = [ "same", 'kj_greater', 'mi_greater' ]

Ensuite, j'ai essayé,

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

Mais il lance un message d'erreur,

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

Au final, j'ai besoin d'une trame de données comme celle-ci,

  A    B    C  A-1  B-1  C-1         que
190  289  300  190  287  267  kj_greater

Si les colonnes A, B et C sont plus élevées que kj_greater, sinon mi_greater, si les 6 sont identiques, alors identiques.

1
user1017373 20 nov. 2018 à 13:51

3 réponses

Meilleure réponse

Éditer

Après un peu de fouille / réflexion, j'ai réalisé que j'avais tort: il s'avère que & est un opérateur logique dans Pandas. & implémente une logique par paire et entre pd.Series et pd.DataFrame objets. Malheureusement, & a une priorité d'opérateur différente de and, vous devez donc être prudent avec elle (dans ce cas, & a une priorité plus élevée que ==, {{X8} } ou <). Le bogue dans le code de l'OP se résume simplement à un manque de parenthèses aux bons endroits.

Donc, pour obtenir le type d'étiquetage que le PO recherchait à l'origine, le code serait:

import numpy as np
import pandas as pd

data= [
    [191, 289, 300, 190, 287, 267],
    [191, 289, 300, 200, 312, 400],
    [191, 289, 300, 191, 289, 300],
    [191, 289, 300, 200, 287, 400],
]
combined_min = pd.DataFrame(data=data, columns=['A', 'B','C','A-1','B-1','C-1'])

cond = lambda x: [(x['A'] == x['A-1']) & (x['B'] == x['B-1']) & (x['C'] == x['C-1']),
                  (x['A'] > x['A-1'])  & (x['B'] > x['B-1'])  & (x['C'] > x['C-1']),
                  (x['A'] < x['A-1'])  & (x['B'] < x['B-1'])  & (x['C'] < x['C-1'])]
choices = ['same', 'kj_greater', 'mi_greater']

combined_min['que'] = np.select(cond(combined_min), choices, default=np.nan)
print(combined_min)

Cela produit:

     A    B    C  A-1  B-1  C-1         que
0  191  289  300  190  287  267  kj_greater
1  191  289  300  200  312  400  mi_greater
2  191  289  300  191  289  300        same
3  191  289  300  200  287  400         nan

En option, cond peut être réduit à une ligne:

from functools import reduce
from operator import eq, gt, lt, and_

cond = lambda x: [reduce(and_, (op(x[c], x['{}-1'.format(c)]) for c in 'ABC')) for op in (eq, gt, lt)]

Bien que cela réduit quelque peu la lisibilité.

2
tel 20 nov. 2018 à 16:53

Le problème est que vous manquez des parenthèses sur les conditions. Chaque condition doit être entourée de parenthèses.

conditions = [(combined_min['A'] == combined_min['A-1']) & (combined_min['B'] == combined_min['B-1']) & (combined_min['C'] == combined_min['C-1']),
          (combined_min['A'] > combined_min['A-1']) & (combined_min['B'] > combined_min['B-1']) & (combined_min['C'] > combined_min['C-1']),
          (combined_min['A'] < combined_min['A-1']) & (combined_min['B'] < combined_min['B-1']) & (combined_min['C'] < combined_min['C-1'])]
1
Tzomas 20 nov. 2018 à 11:24

Votre erreur est dans vos conditions. Le problème est que vous ne comparez pas directement des booléens, mais plutôt un ensemble de pd.Series contenant un booléen, qui ne peut pas être directement comparé comme vous le faites.

Donc:

df['A'] == df['A-1']

Retour:

0    True
dtype: bool

Donc, quand vous le faites:

df['A'] == df['A-1'] & df['A'] == df['A-1']

Vous obtenez l'erreur que vous avez mentionnée. Essayez de séparer chaque terme en utilisant des parenthèses et en utilisant any() pour obtenir le booléen du pd.Series:

((df['A'] == df['A-1']) & (df['A'] == df['A-1'])).any()
1
yatu 20 nov. 2018 à 11:37