web-dev-qa-db-fra.com

Obtenir des lignes qui ont la même valeur sur ses colonnes dans les pandas

Dans les pandas, étant donné un DataFrame D:

+-----+--------+--------+--------+   
|     |    1   |    2   |    3   |
+-----+--------+--------+--------+
|  0  | Apple  | banana | banana |
|  1  | orange | orange | orange |
|  2  | banana | Apple  | orange |
|  3  | NaN    | NaN    | NaN    |
|  4  | Apple  | Apple  | Apple  |
+-----+--------+--------+--------+

Comment puis-je retourner des lignes qui ont le même contenu sur toutes ses colonnes quand il y a trois colonnes ou plus telles qu'elles renvoient ceci:

+-----+--------+--------+--------+   
|     |    1   |    2   |    3   |
+-----+--------+--------+--------+
|  1  | orange | orange | orange |
|  4  | Apple  | Apple  | Apple  |
+-----+--------+--------+--------+

Notez qu'il ignore les lignes lorsque toutes les valeurs sont NaN.

S'il ne s'agissait que de deux colonnes, je fais habituellement D[D[1]==D[2]] mais je ne sais pas comment généraliser cela pour plus de 2 colonnes de données. 

18
kentwait

Semblable à Andy Hayden, répondez avec cocher si min égal à max (alors les éléments de ligne sont tous des doublons):

df[df.apply(lambda x: min(x) == max(x), 1)]
10
lowtech

Mon entrée:

>>> df
        0       1       2
0   Apple  banana  banana
1  orange  orange  orange
2  banana   Apple  orange
3     NaN     NaN     NaN
4   Apple   Apple   Apple

[5 rows x 3 columns]
>>> df[df.apply(pd.Series.nunique, axis=1) == 1]
        0       1       2
1  orange  orange  orange
4   Apple   Apple   Apple

[2 rows x 3 columns]

Cela fonctionne car appeler pd.Series.nunique sur les lignes donne:

>>> df.apply(pd.Series.nunique, axis=1)
0    2
1    1
2    3
3    0
4    1
dtype: int64

Remarque: ceci conserverait toutefois les lignes ressemblant à [nan, nan, Apple] ou [nan, Apple, Apple]. Habituellement, je le veux, mais cela pourrait être la mauvaise réponse pour votre cas d'utilisation.

13
DSM

Je voudrais vérifier si chaque ligne est égale à son premier élément:

In [11]: df.eq(df[1], axis='index')  # Note: funky broadcasting with df == df[1]
Out[11]: 
      1      2      3
0  True  False  False
1  True   True   True
2  True  False  False
3  True   True   True
4  True   True   True

[5 rows x 3 columns]

Si tous les éléments de la ligne ont la valeur True, tous les éléments de la ligne sont identiques:

In [12]: df.eq(df[1], axis='index').all(1)
Out[12]: 
0    False
1     True
2    False
3     True
4     True
dtype: bool

Restreindre aux lignes et éventuellement dropna:

In [13]: df[df.eq(df[1], axis='index').all(1)]
Out[13]: 
        1       2       3
1  orange  orange  orange
3     NaN     NaN     NaN
4   Apple   Apple   Apple

[3 rows x 3 columns]

In [14]: df[df.eq(df[1], axis='index').all(1)].dropna()
Out[14]: 
        1       2       3
1  orange  orange  orange
4   Apple   Apple   Apple

[2 rows x 3 columns]
6
Andy Hayden

basé sur Réponse de DSM , vous voudrez peut-être cette méthode:

import pandas as pd

def filter_data(df):
    df = df.dropna(inplace = True)
    df = df[df.apply(pd.Series.nunique, axis=1)]
    return df
1
Tu Dang

Dans les nouvelles versions de pandas, vous pouvez utiliser nunique

In [815]: df[df.nunique(1).eq(1)]
Out[815]:
        0       1       2
1  orange  orange  orange
4   Apple   Apple   Apple

Détails

In [816]: df
Out[816]:
        0       1       2
0   Apple  banana  banana
1  orange  orange  orange
2  banana   Apple  orange
3     NaN     NaN     NaN
4   Apple   Apple   Apple

In [817]: df.nunique(1)
Out[817]:
0    2
1    1
2    3
3    0
4    1
dtype: int64

In [818]: df.nunique(1).eq(1)
Out[818]:
0    False
1     True
2    False
3    False
4     True
dtype: bool
0
Zero

Vous pouvez utiliser set pour créer une liste des emplacements d'index conformes à votre règle, puis utiliser cette liste pour découper le cadre de données. Par exemple:

import pandas as pd
import numpy as np

D = {0  : ['Apple' , 'banana', 'banana'], 1 : ['orange', 'orange', 'orange'], 2: ['banana', 'Apple', 'orange'], 3: [np.nan, np.nan, np.nan], 4 : ['Apple', 'Apple', 'Apple']} 
DF = pd.DataFrame(D).T

Equal = [row for row in DF.index if len(set(DF.iloc[row])) == 1]

DF.iloc[Equal]

Notez que cela exclut la ligne de valeur manquante sans que vous ayez à exclure expressément les valeurs manquantes. Cela est dû à la nature des valeurs manquantes dans une série.

0
Woody Pride