Pandas применяет функцию к столбцу, пока условие допустимо — более глубокая версия

#python #pandas #dataframe

#python #pandas #фрейм данных

Вопрос:

Скажем, есть фрейм данных:

   Product NewNetProfitMargin  Certain Value   Cost    Price
0       A       50               10              10      20
1       B       12               40              5       17
2       C       13               20              6       12
  

Я хотел бы применить функцию к столбцу цены. Что-то вроде этого :

 def update_price(df):
  while df["New Net Profit Margin"] < df["Certain Value"]:
     df["New Price"] = df["New Total Cost"]   df["Certain Value"] * df["Purchase Price"]
     update_columns() # This function updates the profit margin and cost depended on new price.


df["Price"] = df.apply(update_price,axis=1)
  

Таким образом, в принципе, если new net profit margin продукта меньше определенного значения, функция должна обновлять price до тех пор, пока маржа чистой прибыли не превысит определенное значение.


Проблема, с которой я сталкиваюсь, — это бесконечный цикл. Похоже, что df["Price"] не обновляется для каждой итерации. Может быть из-за того, что значение не возвращается после вычисления, но я понятия не имею, как это сделать.

Фактический набор данных сложный, но я попытался упростить. Надеюсь, это легко понять.


Вот некоторые дополнительные детали:

 def update_columns():
  df["New Comission Amount"] = df.apply(new_commission_amount,axis=1).astype(float)
  df["New Total Cost"] = df.apply(new_total_cost,axis=1).astype(float)
  df["New Net Profit"] = df.apply(new_net_profit,axis=1).astype(float)
  df["New Net Profit Margin"] = df.apply(new_net_profit_margin,axis=1).astype(float)
  print("Columns updated succesfully!")




def new_commission_amount(df):
  
   return df['New Price'] * df['Comission Rate'] 



def new_total_cost(df):
  
  return df['Purchase Price']   df['New Comission Amount']   df['Shipping Cost']



def new_net_profit(df):
  return df["New Price"] - df["New Total Cost"]


def new_net_profit_margin(df):
  
  return df["New Net Profit"] / df["Purchase Price"]
  

Примечание: функция update_columns() использует текущие столбцы и добавляет новые результаты в конец фрейма данных в качестве новых столбцов.

Большую часть времени многие розничные продавцы устанавливают свои цены вручную. Я пытаюсь предотвратить, если кто-то вводит очень низкие числа, я рассчитаю новую цену в соответствии со ставкой и исправлю ее. Чтобы они не теряли деньги

Ответ №1:

Поскольку при работе с массивами вместо этого while задаются новые значения по маске, также для DataFrame используется DataFrame.pipe функция применения для всех:

Редактировать:

 def new_func(df):
     return df['Price'] * df['Cost'] 


def update_columns(df):
  df["New Amount"] = df.apply(new_func,axis=1).astype(float)
  print("Columns updated succesfully!")
  return df


def update_price(df):
   
    df['Price'] = df['Price']*df['Certain Value']   df['Cost']
    # This function updates the profit margin and cost depended on new price.
    df = df.pipe(update_columns) 
    return df
  

Возвращены обновленные столбцы, а также новые столбцы:

 mask =  df["New Net Profit Margin"] < df["Certain Value"]
df1 = df[mask].copy().pipe(update_price)
print (df1)
  Product  New Net Profit Margin  Certain Value  Cost  Price  New Amount
1       B                     12             40     5    685      3425.0
2       C                     13             20     6    246      1476.0
  

Добавьте новые столбцы, заполненные пропущенными значениями с помощью DataFrame.reindex :

 df = df.reindex(df1.columns, axis=1)
print (df)
  Product  New Net Profit Margin  Certain Value  Cost  Price  New Amount
0       A                     50             10    10     20         NaN
1       B                     12             40     5     17         NaN
2       C                     13             20     6     12         NaN
  

Последнее обновление от DataFrame.update :

 df.update(df1)
print (df)
  Product  New Net Profit Margin  Certain Value  Cost  Price  New Amount
0       A                   50.0           10.0  10.0   20.0         NaN
1       B                   12.0           40.0   5.0  685.0      3425.0
2       C                   13.0           20.0   6.0  246.0      1476.0
  

Комментарии:

1. Отличный совет, спасибо, но я получил эту ошибку; TypeError: update_columns() takes 0 positional arguments but 1 was given . Кажется, потому что update_columns() не принимает параметр.

2. @MichaelAdwijk — Каковы входные данные и выходные данные функции update_columns ?

3. На самом деле он содержит 4 разные строки, подобные этой: df["New Profit Margin"] = df.apply(update_profit_margin,axis=1) Эти строки предназначены для обновления определенного столбца. В этом случае update_profit_margin функция просто возвращает формулу и принимает df в качестве параметра. В основном update_columns() функция вызывает эти строки для обновления столбцов в соответствии со своей формулой.

4. @MichaelAdwijk — Возможно ли создать примеры функций update_profit_margin и update_columns и добавить ожидаемый результат при запуске в рассматриваемых примерах данных? Я думаю, update_columns следует возвращать только что-то вроде return column 1 (потому что пример функции). Я спрашиваю, потому что действительно сложно понять, как работает эта функция, если в queston нет описания, только update_columns() — это означает, что нет ввода, нет вывода 🙁

5. Конечно, позвольте мне это сделать! Я пытался упростить, но это становится все сложнее. 🙂

Ответ №2:

Возможно, вы можете выполнить оба обновления в 1 функции следующим образом:

 mask  = df['Net Profit Margin']<df['Certain value']
def update_columns(df):
    df['Price'] = df['Price']*df['Certain value']   df['Cost']
# This updates the profit margin and cost depended on new price.
    df['Net Profit Margin'] = ...
    df['Cost'] = ...
    return df
df[mask] = update_price(df[mask])