Вычисление минимального значения с условием

Столбец добавляется в фрейм данных с минимальным значением для каждого элемента только из столбцов, соответствующих словарю. Как добавить условие при вычислении минимального значения - если значения в выбранных столбцах больше значений в столбце «Col7»?

import pandas as pd
my_dict = {'Item1':['Col1','Col3','Col6'],
'Item2':['Col2','Col4','Col6','Col8']
        }
df=pd.DataFrame({
            'Col0':['Item1','Item2'],
            'Col1':[20,25],
            'Col2':[89,15],
            'Col3':[36,30],
            'Col4':[40,108],
            'Col5':[55,2],
            'Col6':[35,38],
            'Col7':[30,20]
            })

df['min']=df.apply(lambda r:r[[col for col in my_dict.get(r['Col0'], []) if col in r]].min(),axis=1) 

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

df=pd.DataFrame({
            'Col0':['Item1','Item2'],
            'Col1':[20,25],
            'Col2':[89,15],
            'Col3':[36,30],
            'Col4':[40,108],
            'Col5':[55,2],
            'Col6':[35,38],
            'Col7':[30,20],
            'min':[35,38]
            })

Я предполагаю, что в столбце 'min' вам нужно, чтобы минимальное значение из всех столбцов было больше, чем значение в 'Col7' для этой строки, но не должно ли значение для второй строки быть 30 вместо 38? Поскольку 'Col7' содержит значение 20 во второй строке.

Naitzirch 20.04.2024 19:13

Нет, не все, а только из столбцов, соответствующих словарю для каждого элемента. Для элемента 1 — «Col1», «Col3», «Col6», для элемента 2 «Col2», «Col4», «Col6», «Col8» («Col8» не существует в df, и это нормально)

Евгения 20.04.2024 19:20
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
2
90
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Следуя подходу, который вы применяете , ему требуется логическое индексирование (с gt):

df["min"]= (
    df.apply(lambda r: r.reindex(my_dict[r["Col0"]])
             .loc[lambda s: s.gt(r["Col7"])].min(), axis=1)
)

Выход :

    Col0  Col1  Col2  Col3  Col4  Col5  Col6  Col7  min
0  Item1    20    89    36    40    55    35    30   35
1  Item2    25    15    30   108     2    38    20   38

[2 rows x 9 columns]

Рецепт будет довольно простым:

  1. Получите соответствующие столбцы для каждой строки на основе Col0 из my_dict.
  2. Отфильтруйте эти столбцы, чтобы сохранить только значения, превышающие значение в Col7.
  3. Наконец, вычислите min этих отфильтрованных значений.

Вышеупомянутое, выраженное в коде, может выглядеть так:

import pandas as pd

my_dict = {
    'Item1': ['Col1', 'Col3', 'Col6'],
    'Item2': ['Col2', 'Col4', 'Col6', 'Col8']
}
df = pd.DataFrame({
    'Col0': ['Item1', 'Item2'],
    'Col1': [20, 25],
    'Col2': [89, 15],
    'Col3': [36, 30],
    'Col4': [40, 108],
    'Col5': [55, 2],
    'Col6': [35, 38],
    'Col7': [30, 20]
})

# Adding the 'min' column by applying 
# a function across each row
df['min'] = df.apply(lambda row: min([row[col] for col in my_dict.get(row['Col0'], []) if col in row and row[col] > row['Col7']]), axis=1)

print(df)

Не работает, если нет значений, удовлетворяющих условию, например. если условие >(row["Col7"]*1.2), возникнет ошибка: ValueError: min() arg — пустая последовательность

Евгения 20.04.2024 20:24

Как и в ответе Марцина, вы можете добавить and r[col] > r['Col7'] к своему состоянию после if col in r. Итак, эта строка будет выглядеть так:

df['min']=df.apply(lambda r:r[[col for col in my_dict.get(r['Col0'], []) if col in r and r[col] > r['Col7']]].min(),axis=1)

Большое спасибо! Есть ли способ получить имя минимального столбца? Я попытался добавить .astype(float).idxmin(),axis=1), но он говорит ValueError: попытайтесь получить argmin пустой последовательности

Евгения 20.04.2024 20:26

Вы заменили .min()? По коду, который ты сказал? Потому что это работает для меня. Столбец 'min' затем содержит имена столбцов с минимальным значением (то есть выше значения 'Col7'). Мой код: df['min']=df.apply(lambda r:r[[col for col in my_dict.get(r['Col0'], []) if col in r and r[col] > r['Col7']]].astype(float).idxmin(),axis=1)

Naitzirch 20.04.2024 21:29
Ответ принят как подходящий

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

df[['min', 'name']] = df.apply(
    lambda r:min(((r[col], col) for col in my_dict.get(r['Col0'], []) if col in r and r[col] > r['Col7']), default=(np.nan, '')),
    axis=1, result_type='expand'
)

Вывод (для вашего образца данных):

    Col0  Col1  Col2  Col3  Col4  Col5  Col6  Col7  min  name
0  Item1    20    89    36    40    55    35    30   35  Col6
1  Item2    25    15    30   108     2    38    20   38  Col6

Если мы изменим условие на r[col] > r['Col7']*1.2, результат будет таким:

    Col0  Col1  Col2  Col3  Col4  Col5  Col6  Col7   min  name
0  Item1    20    89    36    40    55    35    30   NaN
1  Item2    25    15    30   108     2    38    20  38.0  Col6

Обратите внимание: я использовал NaN и '' в качестве значений по умолчанию, вместо них вы можете использовать все, что захотите.

@Евгения, не волнуйся, я рада, что смогла помочь

Nick 21.04.2024 13:17

Другие вопросы по теме