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.
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)]
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.
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]
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
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
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.