#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. Решение @Quixotic22 лучше, потому что оно проще, но я объясню вам свое. 🙂
3. Объяснено в ответе, @Vega. В основном я просто выбираю не максимальные значения и добавляю их к себе, а затем суммирую каждую строку.