Я пытаюсь преобразовать значение, мой первый столбец, на основе единиц, которые являются вторым столбцом, я пробовал следующее:
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
Не могли бы вы обновить вопрос, добавив в него полный образец кода, чтобы мы могли воспроизвести проблему?
Я обновил вопрос. Спасибо
apply
передает ему аргумент (строку), поэтому вы должны учесть это в своем определении. Я хотел бы транслировать итерацию по уникальным единицам, которые вы хотите изменить.
На этом сайте показано несколько различных способов сделать именно то, о чем вы просите, с разной скоростью.
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% ;-)
Метод 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)
Я протестировал все три метода, и все они работают нормально. Большое спасибо за ваши ответы
Конечно, я просто хотел показать вам, почему ваш первоначальный подход не сработал. Также это решение не требует создания временных столбцов.
у вас есть
x=='b3'
дважды в ваших операторахelif
, делая две разные вещи сdf['value']