Как использовать условие для нескольких столбцов в Pandas?

Я хочу заменить значения в столбцах от P1-6 до P1-95 значениями из столбца family, если значение в определенном столбце > 0. Вот часть моего входного df te_matrix:

     family   P1-6  P1-12  P1-22  P1-25  P1-26  P1-28  P1-88  P1-89  P1-90  P1-92  P1-93  P1-95
 Tourist|20  0.712  0.587  0.838  0.675  0.771  0.952  0.746  0.678  0.603  0.728  0.680  0.759
Stowaway|36  0.740  0.809  0.796  0.699  1.000  0.865  0.814  0.888  0.705  0.758  0.759  0.866
 Stowaway|4  0.000  0.000  0.000  0.000  0.000  0.000  0.880  0.000  0.000  0.000  0.000  0.000

Я пишу это для одной колонки, P1-6:

te_matrix['P1-6'] = te_matrix.apply(lambda row: row['family'] if row['P1-6'] > 0 else row['P1-6'], axis=1)

и работает хорошо:

     family         P1-6  P1-12  P1-22  P1-25  P1-26  P1-28  P1-88  P1-89  P1-90  P1-92  P1-93  P1-95
 Tourist|20   Tourist|20  0.587  0.838  0.675  0.771  0.952  0.746  0.678  0.603  0.728  0.680  0.759
Stowaway|36  Stowaway|36  0.809  0.796  0.699  1.000  0.865  0.814  0.888  0.705  0.758  0.759  0.866
 Stowaway|4        0.000  0.000  0.000  0.000  0.000  0.000  0.880  0.000  0.000  0.000  0.000  0.000

но как использовать его для всех нужных столбцов, не прописывая построчно почти один и тот же код?

Думаю начать с: cols = te_matrix.filter(like='P1-').columns но как применить это к предыдущему коду?

Можете ли вы отредактировать свой вопрос, чтобы предоставить результат te_matrix.to_dict('tight') для воспроизводимости?

mozway 15.07.2024 12:41

@mozway Я только что отредактировал, чтобы исправить выравнивание, ты этого хотел? Или 0.000 в результате P1-6 должно быть 0.0, если это число с плавающей запятой, а столбец является объектом?

wjandrea 15.07.2024 12:49

@wjandrea, спасибо, действительно было бы важно, чтобы OP предоставил этот вывод, чтобы знать типы данных

mozway 15.07.2024 12:52
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
3
66
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Я думаю, вы на правильном пути, используя cols = te_matrix.filter(like='P1-').columns. После этого примените условие к каждому указанному столбцу.

Код:

for col in cols:
    te_matrix[col] = te_matrix.apply(lambda row: row['family'] if row[col] > 0 else row[col], axis=1)

Выход:

      family         P1-6        P1-12        P1-22        P1-25  \
0   Tourist|20   Tourist|20   Tourist|20   Tourist|20   Tourist|20   
1  Stowaway|36  Stowaway|36  Stowaway|36  Stowaway|36  Stowaway|36   
2   Stowaway|4          0.0          0.0          0.0          0.0   

         P1-26        P1-28        P1-88        P1-89        P1-90  \
0   Tourist|20   Tourist|20   Tourist|20   Tourist|20   Tourist|20   
1  Stowaway|36  Stowaway|36  Stowaway|36  Stowaway|36  Stowaway|36   
2          0.0          0.0   Stowaway|4          0.0          0.0   

         P1-92        P1-93        P1-95  
0   Tourist|20   Tourist|20   Tourist|20  
1  Stowaway|36  Stowaway|36  Stowaway|36  
2          0.0          0.0          0.0  

Это вызвало у меня ошибку TypeError: File "/home/emoranska/Pulpit/burak/P1_P4/calculations.py", line 30, in <lambda> te_matrix[col] = te_matrix.apply(lambda row: row['family'] if row[col] > 0 else row[col], axis=1) TypeError: '>' not supported between instances of 'str' and 'int'

emor 15.07.2024 12:36

Пробовали te_matrix[cols] = te_matrix[cols].astype(float)?

JayPeerachai 15.07.2024 12:39

Да, такая же ошибка вылезла..

emor 15.07.2024 12:40

@emor Вам нужно отменить .apply(), прежде чем запускать этот код. Ваш код меняет dtype P1-6 с числового на object (что, кстати, довольно странно).

wjandrea 15.07.2024 12:56

@wjandrea, я проверил, как ты написал, и это действительно странно.. Почему это так работает?

emor 15.07.2024 14:32

@emor О, я имею в виду, странно, что вы меняете типы столбцов. Зачем ты это делаешь?

wjandrea 15.07.2024 15:02
Ответ принят как подходящий

Не используйте apply, он здесь не нужен, это действительно неэффективно.

Используйте логическое индексирование:

df.loc[df['P1-6'].gt(0), 'P1-6'] = df['family']

Выход:

        family         P1-6  P1-12  P1-22  P1-25  P1-26  P1-28  P1-88  P1-89  P1-90  P1-92  P1-93  P1-95
0   Tourist|20   Tourist|20  0.587  0.838  0.675  0.771  0.952  0.746  0.678  0.603  0.728  0.680  0.759
1  Stowaway|36  Stowaway|36  0.809  0.796  0.699  1.000  0.865  0.814  0.888  0.705  0.758  0.759  0.866
2   Stowaway|4          0.0  0.000  0.000  0.000  0.000  0.000  0.880  0.000  0.000  0.000  0.000  0.000

Если вы хотите обновить несколько столбцов одновременно, используйте маску :

cols = df.filter(like='P1-').columns

df[cols] = df[cols].mask(df[cols].gt(0), df['family'], axis=0)

Или, если вы не уверены, содержат ли входные столбцы только числа, с помощью pd.to_numeric:

cols = df.filter(like='P1-').columns

df[cols] = df[cols].mask(df[cols].apply(pd.to_numeric, errors='coerce').gt(0),
                         df['family'], axis=0)

Выход:

        family         P1-6        P1-12        P1-22        P1-25        P1-26        P1-28        P1-88        P1-89        P1-90        P1-92        P1-93        P1-95
0   Tourist|20   Tourist|20   Tourist|20   Tourist|20   Tourist|20   Tourist|20   Tourist|20   Tourist|20   Tourist|20   Tourist|20   Tourist|20   Tourist|20   Tourist|20
1  Stowaway|36  Stowaway|36  Stowaway|36  Stowaway|36  Stowaway|36  Stowaway|36  Stowaway|36  Stowaway|36  Stowaway|36  Stowaway|36  Stowaway|36  Stowaway|36  Stowaway|36
2   Stowaway|4          0.0          0.0          0.0          0.0          0.0          0.0   Stowaway|4          0.0          0.0          0.0          0.0          0.0

Другой способ сделать

cols = te_matrix.filter(like='P1-').columns

возможно

for col in te_matrix.columns:
    if col.startswith("P1-"):
        do_something()

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