Obtén filas que tienen el mismo valor en sus columnas en pandas

En pandas, dado 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 | +-----+--------+--------+--------+ 

¿Cómo devuelvo filas que tienen el mismo contenido en todas sus columnas cuando hay tres columnas o más, de manera que devuelve esto?

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

Tenga en cuenta que omite filas cuando todos los valores son NaN.

Si esto fuera solo dos columnas, normalmente hago D[D[1]==D[2]] pero no sé cómo generalizar esto para más de 2 columnas DataFrames.

Al igual que Andy Hayden, responda con la verificación si min es igual a max (entonces todos los elementos de la fila son duplicados):

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

Mi entrada:

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

Esto funciona porque al llamar a pd.Series.nunique en las filas se obtiene:

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

Nota: esto mantendría, sin embargo, filas que parecen [nan, nan, apple] o [nan, apple, apple] . Por lo general, quiero eso, pero esa podría ser la respuesta incorrecta para su caso de uso.

Me gustaría comprobar si cada fila es igual a su primer elemento:

 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 todos en la fila son Verdaderos, entonces todos los elementos en la fila son iguales:

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

Restringir solo a las filas y opcionalmente 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] 

Según la respuesta de DSM , es posible que desee este método:

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

En las nuevas versiones de pandas, puedes usar nunique

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

Detalles

 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 

Podría usar set para crear una lista de las ubicaciones de índice que se ajustan a su regla, y luego usar esa lista para dividir el dataframe. Por ejemplo:

 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] 

Tenga en cuenta que esto excluye la fila de valor faltante sin que tenga que excluir expresamente los valores faltantes. Esto se debe a la naturaleza de los valores perdidos en una serie.