#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