Получите строки, которые имеют одинаковое значение в своих столбцах в pandas

В pandas, учитывая 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  |
+-----+--------+--------+--------+

Как вернуть строки, которые имеют одинаковое содержимое во всех своих столбцах, когда есть три столбца или больше, что возвращает это:

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

Обратите внимание, что он пропускает строки, когда все значения являются NaN.

Если это были только два столбца, я обычно делаю D[D[1]==D[2]], но я не знаю, как это обобщать для более чем двух столбцов DataFrames.

Ответы

Ответ 1

Как и Энди Хейден, ответьте с проверкой, если min равно max (тогда все элементы строки являются дублирующими):

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

Ответ 2

Моя запись:

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

Это работает, потому что вызов pd.Series.nunique в строках дает:

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

Примечание: это, однако, будет содержать строки, которые выглядят как [nan, nan, apple] или [nan, apple, apple]. Обычно я хочу это, но это может быть неправильный ответ для вашего случая использования.

Ответ 3

Я бы проверил, равна ли каждая строка своему первому элементу:

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]

Если все в строке имеют значение True, то все элементы в строке одинаковы:

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

Ограничьте только строки и, возможно, 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]

Ответ 4

на основе ответа DSM, вам может понадобиться этот метод:

import pandas as pd

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

Ответ 5

Вы можете использовать set для создания списка местоположений индекса, соответствующих вашему правилу, а затем использовать этот список для срезания фрейма данных. Например:

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]

Обратите внимание, что это исключает строку с отсутствующим значением без необходимости явно исключать отсутствующие значения. Это потому, что из-за характера недостающих значений в серии.

Ответ 6

В более новых версиях панд вы можете использовать nunique

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

подробности

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