#python #pandas #dataframe
Вопрос:
Я хочу найти все значения, превышающие 0, в столбцах от n_1 до n_3 включительно и заполнить их столбцами от new_1 до new_3 включительно в порядке от наименьшего к наибольшему, чтобы столбец new_1 имел наименьшее значение, а new_3—наибольшее значение. Если какие-либо столбцы не заполнены из-за недостаточного количества значений для этого, заполните их 0
Я уже задавал подобный вопрос раньше, но ответ не совпадает с ожидаемым результатом
EVENT_ID n_1 n_2 n_3
143419013 0.00 7.80 12.83
143419017 1.72 20.16 16.08
143419021 3.03 12.00 17.14
143419025 2.63 0.00 2.51
143419028 2.38 22.00 2.96
143419030 0.00 40.00 0.00
Ожидаемый Результат:
EVENT_ID n_1 n_2 n_3 new_1 new_2 new_3
143419013 0.00 7.80 12.83 7.80 12.83 0.00
143419017 1.72 20.16 16.08 1.72 16.08 20.16
143419021 3.03 12.00 17.14 3.03 12.00 17.14
143419025 2.63 0.00 2.51 2.51 13.78 0.00
143419028 2.38 22.00 2.96 2.38 2.96 22.00
143419030 3.92 40.00 11.23 40.00 0.00 0.00
Это было решением предыдущего вопроса. Приведенное ниже решение создает новый столбец и сортирует значения от 0 до наибольшего, скорее я хочу, чтобы в новом столбце были значения от 1 и далее. столбец ближе к концу, который не был заполнен из-за недостаточного значения, может быть заполнен 0
df[['new_1', 'new_2', 'new_3']] = np.sort(
df[['n_1', 'n_2', 'n_3']].fillna(0),
axis=1
)
Ответ №1:
Нули в конце
Применил подход, аналогичный исходному решению, близкому к решению:
import pandas as pd
import numpy as np
data = [(143419013,0.00,7.80,12.83),
(143419017,1.72,20.16,16.08),
(143419021,3.03,12.00,17.14),
(143419025,2.63,0.00,2.51),
(143419028,2.38,22.00,2.96),
(143419030,0.00,40.00,0.00)]
df = pd.DataFrame(data, columns=["EVENT_ID", "n_1", "n_2", "n_3"])
df[['new_1', 'new_2', 'new_3']] = np.sort(df[['n_1', 'n_2', 'n_3']]
.replace(0.0, np.nan), axis=1)
df.fillna("0.0", inplace=True)
print(df)
EVENT_ID n_1 n_2 n_3 new_1 new_2 new_3
0 143419013 0.00 7.80 12.83 7.80 12.83 0.0
1 143419017 1.72 20.16 16.08 1.72 16.08 20.16
2 143419021 3.03 12.00 17.14 3.03 12.0 17.14
3 143419025 2.63 0.00 2.51 2.51 2.63 0.0
4 143419028 2.38 22.00 2.96 2.38 2.96 22.0
5 143419030 0.00 40.00 0.00 40.00 0.0 0.0
Этапы этого подхода:
- Создайте копию исходных столбцов n_1 — n_3 с заменой 0.0 на NaN («не число»).
- Отсортируйте их (НаН заканчивается в конце)
- Добавьте их в качестве новых полей в фрейм данных (включая значения NaN).
- Замените все значения NaN в кадре данных на 0.0 (с помощью
fillna
)
(Работает в крайне маловероятном случае, если любое из ваших исходных значений равно бесконечности!)
Что-нибудь
Приведенное выше решение не совсем точно отвечает вопросу, так как предполагается, что оно сортирует элементы от 1 и далее, а не элементы, отличные от нуля.
Эта немного более неуклюжая версия выдает только значения от 1 или больше. Не уверен, какая версия действительно требуется.
data = [(143419013,0.00,7.80,12.83),
(143419017,1.72,20.16,16.08),
(143419021,3.03,12.00,17.14),
(143419025,2.63,0.00,2.51),
(143419028,2.38,22.00,2.96),
(143419030,0.00,40.00,0.00),
# Extra example row, with a negative value, and a value between 0 and 1
(143419030,-1.00,0.40,27.00)]
df = pd.DataFrame(data, columns=["EVENT_ID", "n_1", "n_2", "n_3"])
df[['new_1', 'new_2', 'new_3']] = np.sort(df[['n_1', 'n_2', 'n_3']]
.applymap(lambda v : v if v >= 1 else np.nan), axis=1)
df.fillna("0.0", inplace=True)
print(df)
EVENT_ID n_1 n_2 n_3 new_1 new_2 new_3
0 143419013 0.00 7.80 12.83 7.80 12.83 0.0
1 143419017 1.72 20.16 16.08 1.72 16.08 20.16
2 143419021 3.03 12.00 17.14 3.03 12.0 17.14
3 143419025 2.63 0.00 2.51 2.51 2.63 0.0
4 143419028 2.38 22.00 2.96 2.38 2.96 22.0
5 143419030 0.00 40.00 0.00 40.00 0.0 0.0
6 143419030 -1.00 0.40 27.00 27.00 0.0 0.0
Комментарии:
1. вы просто упростили весь процесс, как и предполагалось. спасибо за ваш ответ. Я никогда не знал, что существует функция вызова applymap
2. Нет проблем, спасибо за обратную связь.
Ответ №2:
Хитрость здесь в том, чтобы заменить 0.0 на np.inf, отсортировать значения в порядке возрастания и откатить замененные значения:
new_df = df.filter(like='n_')
.replace(0., np.inf)
.apply(sorted, axis=1, result_type='expand')
.replace(np.inf, 0.0)
new_df.columns = ['new_1', 'new_2', 'new_3']
out = pd.concat([df, new_df], axis=1)
>>> out
EVENT_ID n_1 n_2 n_3 new_1 new_2 new_3
0 143419013 0.00 7.80 12.83 7.80 12.83 0.00
1 143419017 1.72 20.16 16.08 1.72 16.08 20.16
2 143419021 3.03 12.00 17.14 3.03 12.00 17.14
3 143419025 2.63 0.00 2.51 2.51 2.63 0.00
4 143419028 2.38 22.00 2.96 2.38 2.96 22.00
5 143419030 0.00 40.00 0.00 40.00 0.00 0.00
Комментарии:
1. Если кто-то знает лучший способ переименования столбцов, не стесняйтесь редактировать мой пост
2. Не думайте, что вам нужно
lambda
здесь; вы можете просто сделать.apply(sorted, axis=1...