Как найти максимальное значение 3 столбцов и умножить остальные 2 с фиксированным коэффициентом, а затем сложить все вместе?

#python #pandas

#питон #панды

Вопрос:

У меня есть большой фрейм данных df:

 df = pd.DataFrame(  {  "length": [1200,600, 600,1201, 600, 600, 500, 700],  "width": [600, 1200, 600, 600, 1201, 600, 800, 700],  "height": [600, 600, 1200, 600, 600, 1201, 800, 700],  } )  
длина ширина высота
1200 600 600
600 1200 600
600 600 1200
1201 600 600
600 1201 600
600 600 1201
500 800 800
700 700 700

Мне нужно найти наибольшее значение в строке, затем умножить другое на *2 и сложить все вместе.

Итак, формула такова:

 highest_value   (lower_value_1 * 2)   (lower_value_2 * 2)  
  • Например, для строки 1: 1200 (600 * 2) (600 * 2) = 3600
  • Например, для строки 7: 800 (800 * 2) (500 * 2) = 3400
  • Например, для строки 8: 700 (700 * 2) (700 * 2) = 3500

Результат должен быть:

длина ширина высота обхват
1200 600 600 3600
600 1200 600 3600
600 600 1200 3600
1201 600 600 3601
600 1201 600 3601
600 600 1201 3601
500 500 800 3400
700 700 700 3500

Я могу найти максимум 3 строки с

 df[["length ", "width ", "height "]].max(axis=1)  

но мне нужна помощь с остальным.

Ответ №1:

Это кажется более простым решением

 df['New'] = df.sum(axis=1)*2 - df.max(axis=1)  

Правка, предназначалась для копирования этого

 df['Girth'] = df.apply(lambda x: sum(x)*2 - max(x), axis = 1)  

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

1. Спасибо, это работает! Является ли это решение векторизованным? Мой фрейм данных довольно большой.

2. В этом случае я бы использовал свое первое решение

Ответ №2:

Вот очень быстрое векторизованное решение, которое использует преимущества широковещания numpy для достижения очень высокой производительности:

 mask = pd.DataFrame(df.to_numpy() != df.max(axis=1).to_numpy().reshape(-1,1), columns=df.columns) df['girth'] = df.add(df[mask].fillna(0)).sum(axis=1)  

Выход:

 gt;gt;gt; df  length width height girth 0 1200 600 600 3600.0 1 600 1200 600 3600.0 2 600 600 1200 3600.0 3 1201 600 600 3601.0 4 600 1201 600 3601.0 5 600 600 1201 3601.0  

На моем 8-ядерном процессоре Intel Core i9 с частотой 3,6 ГГц это заняло около ~950 мс для 6 000 000 (6 миллионов) строк.


В основном то, что мы здесь делаем, это:

  1. Создание маски, которая выбирает все значения в кадре данных, которые не являются максимальными в строке, в которой они находятся
  2. Снова добавляем значения, выбранные этой маской (не максимальные значения), в кадр данных
  3. Суммирование полученных строк

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

1. Спасибо вам за ваше решение. К сожалению, я ничего не понимаю. Если у вас есть время, было бы неплохо объяснить код.

2. Решение @Quixotic22 лучше, потому что оно проще, но я объясню вам свое. 🙂

3. Объяснено в ответе, @Vega. В основном я просто выбираю не максимальные значения и добавляю их к себе, а затем суммирую каждую строку.