Подсчитайте количество одинаковых значений в DataFrame Python

У меня есть фрейм данных с двумя столбцами: хеш и результаты.

В хеш-столбце указан идентификатор задачи, он может повторяться несколько раз.

Столбец результатов содержит ответ пользователя на это задание. Ответы содержат конкретные строковые значения типа: «Да», «Нет», «Возможно», 404».

Моя задача — просчитать согласованность ответов пользователей.

Например, если на задачу с одним хешем 3 пользователя ответили одинаково, то согласованность равна 100%. Если 2 из 3 ответили одинаково, то 66,6. Если одно из 3, то 33,3%. Если все ответили по-разному, то 0.

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

Подскажите пожалуйста, какие функции можно использовать для решения этой проблемы.

дф, например:

df = pd.DataFrame({'hash': list('AAABBBCCCCDDD'),
               'results': ['Yes', 'No', 'No',
                           'Yes', 'Yes', 'Yes',
                           'Perhaps', 'Yes', '404', 'Perhaps',
                           'Yes', 'No', 'Perhaps',
                          ]
              })

Он дает номер каждого ответа. Как получить только то количество ответов, которые встречаются чаще всего?

Dmitry 31.07.2024 13:51

Да, именно количество этих наиболее частых значений для каждого хеша.

Dmitry 31.07.2024 13:57

Моя вина, я изначально неправильно понял вопрос.

dydev 31.07.2024 14:04

прочитайте уведомление: минимальный воспроизводимый пример

Panda Kim 31.07.2024 14:07
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
4
62
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Поскольку вы не предоставляете никакого справочного кода, я создаю мини-скрипт Python для имитации вашего кода. Это то, что я использовал:

Сначала я создаю функцию, которая может принимать df и выполнять все операции.

def calculate_consistency(df):

Затем, прежде всего, я сгруппировал все записи по хешу и столбцам результатов:

df.groupby('hash')['result'].value_counts().unstack(fill_value=0)
  • df.groupby('hash') эта функция создает объект GroupBy, в котором все строки с одинаковым значением хеша группируются вместе.
  • [результат] Из каждой группы выбирается только столбец «результат». Сейчас мы работаем с группами значений «результата» для каждого уникального «хеша».
  • .value_counts() Этот метод подсчитывает вхождения каждого уникального значения в столбце «результат».
  • .unstack() Преобразует серию серий (полученную из value_counts) в DataFrame. Каждое уникальное значение результата становится столбцом. Каждый «хеш» становится строкой.
  • fill_value=0: это аргумент функции unstack(). Он заполняет все пропущенные значения (NaN) 0.

Затем подсчитайте общее количество ответов для каждого хэша.

total_responses = grouped.sum(axis=1)

Чтобы найти максимальное количество для каждого хеша

max_counts = grouped.max(axis=1)

И, наконец, рассчитайте процент согласованности и верните согласованность.

consistency = (max_counts / total_responses) * 100
return consistency

Полный код с примером выглядит так:

import pandas as pd

def calculate_consistency(df):
    grouped = df.groupby('hash')['result'].value_counts().unstack(fill_value=0)
    total_responses = grouped.sum(axis=1)
    max_counts = grouped.max(axis=1)
    consistency = (max_counts / total_responses) * 100
    return consistency


df = pd.DataFrame({'hash': ['A', 'A', 'A', 'B', 'B', 'C', 'C', 'C'], 'result': ['Yes', 'Yes', 'No', 'Yes', 'No', 'Perhaps', '404', 'Yes']})

result = calculate_consistency(df)
print(result)

Дайте мне знать, если это полезно для вас, удачи!

Спасибо большое, все работает и очень подробно. Остаётся одно, если все ответы разные, это тоже даёт 33%, как в этом случае сделать, чтобы выдавало 0?

Dmitry 31.07.2024 14:25

В этом случае нам также следует позаботиться о unique_responses, поэтому после переменной max_counts мы должны добавить новую переменную, вызывающую unique_responses = (grouped > 0).sum(axis=1), чтобы вычислить количество уникальных ответов для каждого хеша, и, наконец, обновите переменную согласованности для этой новой концепции.

Luis Villalba Ballesteros 31.07.2024 14:49

Не забудьте проголосовать за полезный вопрос и выбрать наиболее подходящий для вашего случая! Это было приятно

Luis Villalba Ballesteros 31.07.2024 16:06

IIUC, вы можете построить перекрестную таблицу , получить (первое) наиболее распространенное значение и вычислить согласованность:

df = pd.DataFrame({'hash': list('AAABBBCCCCDDD'),
                   'results': ['Yes', 'No', 'No',
                               'Yes', 'Yes', 'Yes',
                               'Perhaps', 'Yes', '404', 'Perhaps',
                               'Yes', 'No', 'Perhaps',
                              ]
                  })

# compute crosstab
tmp = pd.crosstab(df['hash'], df['results'])

# are all values different?
m = tmp.le(1).all(axis=1)

out = (pd.DataFrame({'top_answer': tmp.idxmax(axis=1).mask(m, '-'),
                     'consistency': tmp.max(axis=1)
                                       .div(tmp.sum(axis=1))
                                       .mask(m, 0)
                    })
         .reset_index()
      )

Выход:

  hash top_answer  consistency
0    A         No     0.666667
1    B        Yes     1.000000
2    C    Perhaps     0.500000
3    D          -     0.000000

Другой подход с groupby:

df = pd.DataFrame({'hash': list('AAABBBCCCCDDD'),
                   'results': ['Yes', 'No', 'No',
                               'Yes', 'Yes', 'Yes',
                               'Perhaps', 'Yes', 'Yes', 'Perhaps',
                               'Yes', 'No', 'Perhaps',
                              ]
                  })

g = df.groupby('hash')['results']

# number of answers
na = g.size()

# number of unique answers
nu = g.nunique()

# most common answer
mc = g.agg(lambda x: x.mode().str.cat(sep='/'))

# count of most frequent
cnt = g.value_counts().groupby(level='hash').max()

# are all answers different?
m = nu == na

out = (pd.DataFrame({'top_answer': mc.mask(m, '-'),
                     'consistency': (nu/na).mask(m, 0),
                     'nb_answers': na,
                     'nb_unique_answers': nu,
                     'count_top': cnt,
                    })
         .reset_index()
      )

Вариант вычисления наиболее распространенного ответа:

# count of most frequent
tmp = g.value_counts().reset_index(1)
cnt = tmp.groupby(level=0)['count'].max()

# most common answer
mc = (tmp.loc[tmp['count'].eq(cnt),'results']
         .groupby(level=0).agg('/'.join)
     )

Обратите внимание, что в случае ничьей это объединит наиболее распространенные ответы, если вы хотите использовать только одно (случайное) mc = g.agg(lambda x: x.mode()[0]).

Выход:

  hash   top_answer  consistency  nb_answers  nb_unique_answers  count_top
0    A           No     0.666667           3                  2          2
1    B          Yes     0.333333           3                  1          3
2    C  Perhaps/Yes     0.500000           4                  2          2
3    D            -     0.000000           3                  3          1

Это тоже отлично работает, большое спасибо. Только если все ответы разные, мне нужно получить 0, подскажите плс как это можно сделать наиболее рационально

Dmitry 31.07.2024 14:45

@Дмитрий, посмотрите, соответствует ли вам обновление, но, пожалуйста, отредактируйте свой вопрос, чтобы добавить минимально воспроизводимый пример с ожидаемым результатом (вы можете повторно использовать мой пример, если хотите)

mozway 31.07.2024 14:55

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