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

#python #pandas #dataframe #numpy

Вопрос:

У меня есть df:

 dfs = """
    contract Valindex0  RB  Valindex1
2   A00118  51  0   50
3   A00118  42  1   47
4   A00118  44  1   47

"""
df = pd.read_csv(StringIO(dfs.strip()), sep='s ')
 

df:

   contract  Valindex0  RB  Valindex1
2   A00118         51   0         50
3   A00118         42   1         47
4   A00118         44   1         47
 

Я хочу добавить новый столбец в каждую строку df[‘Valindex’],

это значение столбца равно либо

  df['Valindex0']
 

или

  df['Valindex1']
 

это зависит от df[‘RB’]:

 if df['RB']==0:
   df['Valindex'] = df['Valindex0']
elif df['RB']==1:
  df['Valindex'] = df['Valindex1']  
 

Сейчас я использую apply lambda,но это очень медленно:

 df['Valindex'] = df.apply(
    lambda df: df["Valindex"   str(df["RB"])], axis=1)
 

Результат должен выглядеть следующим образом:

     contract    Valindex0   RB  Valindex1   Valindex
2   A00118            51    0   50          51
3   A00118            42    1   47          47
4   A00118            44    1   47          47
 

Есть какой-нибудь более быстрый способ?

Ответ №1:

использовать np.where() :

 df["Valindex"] = np.where(df["RB"].eq(0), df["Valindex0"], df["Valindex1"])
 

или

используйте np.select() для нескольких случаев и условий:

 conditions = [df["RB"].eq(0), df["RB"].eq(1)]
labels = [df["Valindex0"], df["Valindex1"]]
df["Valindex"] = np.select(conditions, labels)
 

выход из df :

     contract    Valindex0   RB  Valindex1   Valindex
2   A00118      51          0   50          51
3   A00118      42          1   47          47
4   A00118      44          1   47          47
 

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

1. Отредактировал свой ответ, чтобы добавить ссылки на упомянутые функции. Не стесняйтесь возвращать изменения, если это не в порядке.

Ответ №2:

Ты можешь попробовать Series.where .

 df["Valindex"] = df["Valindex0"].where(df["RB"].eq(0), df["Valindex1"])


  contract  Valindex0  RB  Valindex1  Valindex
2   A00118         51   0         50        51
3   A00118         42   1         47        47
4   A00118         44   1         47        47
 

Ответ №3:

Давайте просто попробуем назначить

 df['Valindex'] = df['Valindex0']

df.loc[df.RB==1,'Valindex'] = df['Valindex1']
 

Ответ №4:

Запустив кучу методов и рассчитав время каждого метода на 1000 строк, кажется, что метод 3, предложенный Анурагом, работает лучше всего. Время каждого прогона меняется, но рейтинг не меняется.

 #Method 1 (original) - 0.0168s
df['Valindex'] = df.apply(lambda df: df["Valindex"   str(df["RB"])], axis=1)

#Method 2 - 0.0015s
df['Valindex'] = (df['RB'] == 0 ) * df['Valindex0']   df['RB'] * df['Valindex1']

#Method 3 - 0.0009s
df["Valindex"] = np.where(df["RB"].eq(0), df["Valindex0"], df["Valindex1"])

#Method 4 - 0.0014s
df["Valindex"] = df["Valindex0"].where(df["RB"].eq(0), df["Valindex1"])

#Method 5 - 0.0022s
df['Valindex'] = df['Valindex0']
df.loc[df.RB==1,'Valindex'] = df['Valindex1']