Проверьте, совпадают ли все значения в столбце dataframe

Я хочу быстро и легко проверить, совпадают ли все значения столбцов для counts в фрейме данных:

В:

import pandas as pd

d = {'names': ['Jim', 'Ted', 'Mal', 'Ted'], 'counts': [3, 4, 3, 3]}
pd.DataFrame(data=d)

Вне:

  names  counts
0   Jim       3
1   Ted       4
2   Mal       3
3   Ted       3

Я хочу простое условие, что if all counts = same value, затем print('True').

Есть ли быстрый способ сделать это?

как насчет if len(df['counts'].unique()) ==1: print(True)

Sociopath 28.01.2019 16:56
df.counts.nunique() == 1?
ernest_k 28.01.2019 16:57

df.counts.drop_duplicates().shape[0] == 1

Richard B 10.11.2021 18:18
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
41
4
58 580
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Эффективный способ сделать это — сравнить первое значение с остальными и использовать all:

def is_unique(s):
    a = s.to_numpy() # s.values (pandas<0.24)
    return (a[0] == a).all()

is_unique(df['counts'])
# False

Хотя наиболее интуитивно понятной идеей может быть подсчет количества значений unique и проверка, есть ли только одно, это будет излишне усложнять то, что мы пытаемся сделать. Numpy's' np.unique, вызываемый pandas' nunique, реализует сортировку базовых массивов, которая имеет среднюю сложность O(n·log(n)) с использованием быстрая сортировка (по умолчанию). Вышеупомянутый подход — O(n).

Разница в производительности становится более очевидной, когда мы применяем это ко всему фрейму данных (см. ниже).


Для всего фрейма данных

В случае, если вы хотите выполнить ту же задачу для всего фрейма данных, мы можем расширить вышеизложенное, установив axis=0 в all:

def unique_cols(df):
    a = df.to_numpy() # df.values (pandas<0.24)
    return (a[0] == a).all(0)

Для общего примера мы получим:

unique_cols(df)
# array([False, False])

Вот сравнение вышеуказанных методов с некоторыми другими подходами, такими как использование nunique (для pd.Series):

s_num = pd.Series(np.random.randint(0, 1_000, 1_100_000))

perfplot.show(
    setup=lambda n: s_num.iloc[:int(n)], 

    kernels=[
        lambda s: s.nunique() == 1,
        lambda s: is_unique(s)
    ],

    labels=['nunique', 'first_vs_rest'],
    n_range=[2**k for k in range(0, 20)],
    xlabel='N'
)


Ниже приведены тайминги для pd.DataFrame. Давайте также сравним с подходом numba, который здесь особенно удобен, поскольку мы можем воспользоваться преимуществом сокращения, как только увидим повторяющееся значение в данном столбце (примечание: подход numba будет работать только с числовыми данными):

from numba import njit

@njit
def unique_cols_nb(a):
    n_cols = a.shape[1]
    out = np.zeros(n_cols, dtype=np.int32)
    for i in range(n_cols):
        init = a[0, i]
        for j in a[1:, i]:
            if j != init:
                break
        else:
            out[i] = 1
    return out

Если сравнить три метода:

df = pd.DataFrame(np.concatenate([np.random.randint(0, 1_000, (500_000, 200)), 
                                  np.zeros((500_000, 10))], axis=1))

perfplot.show(
    setup=lambda n: df.iloc[:int(n),:], 

    kernels=[
        lambda df: (df.nunique(0) == 1).values,
        lambda df: unique_cols_nb(df.values).astype(bool),
        lambda df: unique_cols(df) 
    ],

    labels=['nunique', 'unique_cols_nb', 'unique_cols'],
    n_range=[2**k for k in range(0, 20)],
    xlabel='N'
)

Можем проверить, если нет. уникальных значений в столбце равно 1.

Anupam Kumar 20.01.2021 09:36

Поиск уникальных значений имеет излишне высокую сложность, чтобы проверить это. Он включен в графики производительности, чтобы было понятно @AnupamKumar

yatu 20.01.2021 09:39

Вы правы, я совсем забыл о производительности.

Anupam Kumar 20.01.2021 09:49

Обновление с помощью np.unique

len(np.unique(df.counts))==1
False

Или

len(set(df.counts.tolist()))==1

Или

df.counts.eq(df.counts.iloc[0]).all()
False

Или

df.counts.std()==0
False

Это: df.counts.is_unique - у меня не сработало, но df.counts.nunique() == 1 работает. Я использую Python 2.7 в Windows.

MEdwin 28.01.2019 17:02

@MEdwin Я имею в виду твою версию панд.

BENY 28.01.2019 17:10

Моя версия панд: 0.23.4

MEdwin 28.01.2019 17:11

@MEdwin проверьте ссылку pandas.pydata.org/pandas-docs/stable/reference/api/…, если все еще возвращает ошибку, отправьте сообщение об ошибке в github.

BENY 28.01.2019 17:17

Плохой ответ: is_unique проверяет уникальность значений в столбце, т. е. отсутствие дубликатов. То, что было задано, заключается в проверке того, что все значения в столбце одинаковы, а это совсем другое.

rickyalbert 04.06.2019 14:18

Я думаю, что nunique делает гораздо больше работы, чем необходимо. Итерация может остановиться на первом различии. Это простое и универсальное решение использует itertools:

import itertools

def all_equal(iterable):
    "Returns True if all elements are equal to each other"
    g = itertools.groupby(iterable)
    return next(g, True) and not next(g, False)

all_equal(df.counts)

Это можно использовать даже для поиска столбцов все с постоянным содержимым за один раз:

constant_columns = df.columns[df.apply(all_equal)]

Немного более читаемая, но менее производительная альтернатива:

df.counts.min() == df.counts.max()

Добавьте сюда skipna=False, если необходимо.

Я предпочитаю:

df['counts'].eq(df['counts'].iloc[0]).all()

Я считаю, что его легче всего читать, и он работает со всеми типами значений. Я также нашел это достаточно быстро в моем опыте.

Было бы здорово объяснить, почему этот метод предпочтительнее другого.

TocToc 15.12.2020 10:43

Добавил объяснение.

Mitar 15.12.2020 18:29

Предупреждение: это вернет False, если df['counts'] будет равен None.

Daniel Hjertholm 16.01.2021 21:41

Другие вопросы по теме