Определение функции из двух столбцов в Pandas

Я пытаюсь преобразовать значение, мой первый столбец, на основе единиц, которые являются вторым столбцом, я пробовал следующее:

def my_conversion():
    for x in df['unit']:
        if x == 'b1':
            return(df['value'] * 0.125)
        elif x == 'b2':
            return(df['value'] * 0.25)
        elif x == 'b3':
            return(df['value'] * 0.00781)
        elif x == 'b4':
            return(df['value'] / 3785411800000)
        else:
            return(df['value'])

Затем я использую применить для создания нового столбца:

df['value_converted'] = df['value'].apply(my_conversion)

Я получаю следующую ошибку:

my_conversion() takes 0 positional arguments but 1 was given

у вас есть x=='b3' дважды в ваших операторах elif, делая две разные вещи с df['value']

KenHBS 17.12.2018 14:21

Не могли бы вы обновить вопрос, добавив в него полный образец кода, чтобы мы могли воспроизвести проблему?

Prince Francis 17.12.2018 14:23

Я обновил вопрос. Спасибо

GNJ 17.12.2018 14:24
apply передает ему аргумент (строку), поэтому вы должны учесть это в своем определении. Я хотел бы транслировать итерацию по уникальным единицам, которые вы хотите изменить.
Andrew 17.12.2018 14:29
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
4
45
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

На этом сайте показано несколько различных способов сделать именно то, о чем вы просите, с разной скоростью.

https://realpython.com/fast-f flexible-pandas/

Вот быстрый пример, который я протестировал и работает.

def apply_tariff_isin(df):
    b1 = df.unit.isin(['b1'])
    b2 = df.unit.isin(['b2'])
    b3 = df.unit.isin(['b3'])
    b4 = df.unit.isin(['b4'])


    df.loc[b1, 'new_value'] = df.loc[b1, 'value'] * .125
    df.loc[b2,'new_value'] = df.loc[b2, 'value'] * .25
    df.loc[b3,'new_value'] = df.loc[b3, 'value'] * .00781
    df.loc[b4,'new_value'] = df.loc[b4, 'value'] / 3785411800000
Ответ принят как подходящий

Вы можете сопоставить значения в df['unit'] числовому значению, которое есть в ваших if-операторах, с помощью .map(). Затем вы можете поэлементно умножить эти сопоставленные значения на df['value']:

m = {'b1' : .125, 'b2' : .25, 'b3':  0.00781, 'b4': 1./3785411800000}
df['value_converted'] = df['unit'].map(m).fillna(1) * df['value']

Эквивалентным, но немного более сложным, длинным и явным будет:

mapping_dictionary = {'b1': .125, 
                      'b2': .250, 
                      'b3': .00781, 
                      'b4': 1./37854118}

df['mapped_values'] = df['unit'].map(mapping_dictionary).fillna(1)
df['value_converted'] = df['mapped_values'] * df['value']

Я знаю, это не отвечает на вопрос, но решает вашу проблему.

Я бы посоветовал позаботиться о том, чтобы вы полностью ответили на вопрос ... это означает, что вы лучше, чем правильный ответ на 80% ;-)

cs95 17.12.2018 14:29

Метод apply по умолчанию проходит через все строки, поэтому вам не нужно создавать цикл внутри вашей функции. Должно получиться так:

def my_conversion(row):
    if row['unit']=='b1':
        return(row['value']*0.125)
    elif row['unit']=='b2':
        return(row['value']*0.25)
    elif row['unit']=='b3':
        return(row['value']*0.00781)
    elif row['unit']=='b4':
        return(row['value']/3785411800000)
    else:
        return(row['value'])

И вам нужно вызвать его для всего df:

df['value_converted'] = df.apply(my_conversion, axis=1)

Я протестировал все три метода, и все они работают нормально. Большое спасибо за ваши ответы

GNJ 17.12.2018 14:53

Конечно, я просто хотел показать вам, почему ваш первоначальный подход не сработал. Также это решение не требует создания временных столбцов.

Damian Russak 17.12.2018 15:03

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