Python : Как вернуть наиболее часто встречающееся значение в каждой строке в зависимости от исправленных столбцов?

#python #pandas #numpy

Вопрос:

У меня есть фрейм данных, как показано ниже:

 import pandas as pd   # intialise data of lists. data = {'Name':['Tom', 'nick', 'krish', 'jack'],  'Book1':[20, 21, 19, 18],  'Book2':[20,'', 12, 20],  'Book3':[31, 21, 17, 16],  'Book4':[31, 19, 18, 16]}   # Create DataFrame df = pd.DataFrame(data)   # Print the output. print(df)  
 Name Book1 Book2 Book3 Book4 Tom 20 20 31 31 nick 21 21 19 krish 19 12 17 18 jack 18 20 16 16  

Я хочу получить результат ниже, который сравнивает столбцы Book1, Book2, Book3 и Book4. Для вывода строки Tom есть два 20 и два 31, так как число значения равно валентности, поэтому в этом случае он предпочтет, чтобы значение пришло первым, то есть Book1, поэтому выходной столбец равен 20. Для ника строки было два числа 21 и одно число 19, поэтому для выходного столбца потребуется наибольшее число встречаемости, которое равно 21. В то время как для строки krish не было повторяющегося числа, поэтому в выходном столбце я хочу исправить его как «Mix» .

Выходной столбец, как показано ниже:

 Name Book1 Book2 Book3 Book4 Output Tom 20 20 31 31 20 nick 21 21 19 21 krish 19 12 17 18 Mix jack 18 20 16 16 16  

У кого-нибудь есть идеи? Я видел, что есть функция режима, но она не была применима в данном случае, пожалуйста, помогите, спасибо

Ответ №1:

Воспользуйся value_counts :

 max_val = lambda x: x.value_counts().index[0]   if x.value_counts().iloc[0] gt; 1 else 'Mix'  df['Output'] = df.filter(like='Book').apply(max_val, axis=1) print(df)  # Output:  Name Book1 Book2 Book3 Book4 Output 0 Tom 20 20 31 31 20 1 nick 21 21 19 21 2 krish 19 12 17 18 Mix 3 jack 18 20 16 16 16  

Обновить

Если вы пользуетесь Python gt;= 3.8 , вы можете воспользоваться оператором walrus (избегайте двойного звонка в value_counts :

 max_val = lambda x: v.index[0] if (v := x.value_counts()).iloc[0] gt; 1 else 'Mix' df['Output'] = df.filter(like='Book').apply(max_val, axis=1)  

Комментарии:

1. Я получаю 31 в качестве вывода для Тома

2. Вы повторно использовали мой код? Какова ваша версия Панд?

3. да, я скопировал и вставил, я использую pandas 0.25.1

4. Просто обновите Панд. Версии ниже 1.0.0 являются устаревшими.

5. будет сделано, спасибо

Ответ №2:

Мы можем использовать вашу идею mode для получения желаемого результата. Во-первых, нам нужно преобразовать соответствующие столбцы в числовые типы данных:

 temp = (df  .filter(like='Book')  .apply(pd.to_numeric)  .mode(1)  )  # compute for values # nulls exist only if there are duplicates output = np.where(temp.notna().all(1),  # value if True  'Mix',  # if False, pick the first modal value,   temp.iloc[:, 0])   df.assign(output = output)   Name Book1 Book2 Book3 Book4 output 0 Tom 20 20 31 31 20.0 1 nick 21 21 19 21.0 2 krish 19 12 17 18 Mix 3 jack 18 20 16 16 16.0