Примените функцию к кадру данных Pandas строка за строкой (axis = 0), чтобы создать четыре новых столбца

1

Я играл с этим, но я не могу даже заставить простейшее дело работать, поэтому я собираюсь попросить помощи.

У меня большой фрейм данных, и я пытаюсь добавить в него четыре новых столбца. Значения для каждого столбца зависят от данных в строке согласно операторам if ниже.

Вот что я набросал до сих пор:

import pandas as pd

d = {'Signal': [0,1,1,0],
   'Win': [False,True,False,False],
   'Odds': [1.1, 1.2, 1.3, 1.4],
   'Helper': [True,False,False,False],
   'before': ['','','',''],
   'stake':['','','',''],
   'result':['','','',''],
   'after':['','','','']
}

df = pd.DataFrame(d)

def function(df, start, stake_size):
   '''
   takes in three arguments: a dataframe, a start number as int and 
   stake_size as int
   the function fills up before, stake, result, after columns row by row 
   using the IF statements below
   '''
   #if df['Helper']:
   #    df['before'] = start
   #else:
   #    df['before'] = df['after'].shift(1)

   df['before'] = start #This is so I can replicate the example

   if df['Signal'] == 0:
       df['stake'] = 0
       df['result'] = 0
   elif df['Signal'] == 1:
       df['stake'] = df['before'] * (stake_size/100)

   if (df['Signal'] == 1 & df['Win'] == True):
       df['result'] = (df['stake'] * df['odds']) - df['stake']
   else:
       df['result'] = df['stake'] * -1

   df['after'] = df['before'] + df['result']

   return df

df.apply(function, args=(100,5), axis=1)

Достаточно сказать, что это никуда меня не приведет.

Я привык использовать .apply(function, axis=1) для создания столбцов, но это не сработает в этом случае, так как для того, чтобы вычислять раньше, мне нужно вычислять после в той же строке. То есть. каждая строка должна быть заполнена последовательно. Вот почему я попытался подойти к этому как к функции, которая получает строку и вычисляет значения для четырех новых столбцов.

Буду признателен за любую помощь или подобные примеры, чтобы расклеить здесь. Благодарю.

РЕДАКТИРОВАТЬ: Я воспользовался советом от HakunaMaData и добавил столбец Helper к df, чтобы убедиться, что я применю первое выражение if, как я и предполагал. Сначала я думал, что .shift будет работать здесь, но это не сработает, потому что я не могу сместить весь фрейм данных при применении вдоль строки, верно?

Есть ли другой способ, которым я могу подойти к этому?

Предполагаемый результат, который я ищу:

answer = {'Signal': [0,1,1,0],
          'Win': [False,True,False,False],
          'Odds': [1.1, 1.2, 1.3, 1.4],
          'Helper': [True,False,False,False],
          'before': [100,100,101,94.95],
          'stake':[0,5,5,0],
          'result':[0,1,-5,0],
          'after':[100,101,95.95,95.95]
          }
  • 0
    Могут ли моды изменить название этого поста? Я был довольно смущен, когда я впервые опубликовал это, и теперь это не имеет смысла. Должно быть что-то похожее на: отслеживание и использование значения предыдущей строки при использовании .apply для заполнения новых столбцов в фрейме данных pandas
Теги:
pandas
dataframe

2 ответа

2
Лучший ответ

Здесь есть несколько вопросов:

До, Ставка, После, Результат и т.д. Должны быть числовыми типами, а не строками. Так что меняй их - вот так:

d = {'Signal': [0,1,1,0],
   'Win': [False,True,False,False],
   'Odds': [1.1, 1.2, 1.3, 1.4],
   'before': [0]*4,
   'stake':[0]*4,
   'result':[0]*4,
   'after':[0]*4
}

Теперь остальная часть кода обычно работает:

df = pd.DataFrame(d)

def function(df, start, stake_size):

   '''
   takes in three arguments: a dataframe, a start number as int and 
   stake_size as int
   the function fills up before, stake, result, after columns row by row 
   using the IF statements below
   '''

   global after #Create a global variable to track the value in the previous row

   if df.name == 0: 
       df['before'] = start
   else: 
        df['before'] = after 

   if df['Signal'] == 0:
       df['stake'] = 0
       df['result'] = 0
   elif df['Signal'] == 1:
       df['stake'] = df['before'] * (stake_size/100)

   if (df['Signal'] == 1 & df['Win'] == True):
       df['result'] = (df['stake'] * df['odds']) - df['stake']
   else:
       df['result'] = df['stake'] * -1

   df['after'] = df['before'] + df['result']

   after = df['after'] #assign the value to the global variable at the end

   return df

Наконец, используйте ось строки, а не ось столбца:

df.apply(function, args=(100,5), axis=1)

Вот вывод:

Изображение 174551

  • 0
    Спасибо @HakunaMaData, это большой шаг вперед. Я могу повторить этот результат и внести несколько небольших изменений в другие ошибки, которые я редактировал выше. Однако я хотел, чтобы столбец ['before'] вел себя по-другому. В результате должно быть: 100, 100, 101, 94,95. Вы также можете предоставить какие-либо указатели на это?
  • 0
    Вы можете использовать глобальную переменную для отслеживания значения after из предыдущей строки. Кроме того ... Я не могу добраться до 94,95 ... Я думаю, что это должно быть 95,95 вместо этого на основе предоставленных вами данных.
Показать ещё 1 комментарий
1

сначала вам нужно изменить свою функцию, вы будете применять строку за строкой, используя: df.apply(lambda x: function(x,100,5), axis=1)

Тогда ваша подпись функции будет:

def function(row,start,stake_size):
    # Your conditions...
    return row

Осторожно! В этом случае вы манипулируете не кадром данных с помощью apply() а строкой, поэтому вам придется адаптировать свой код в функции.

Надеюсь это поможет !

  • 0
    Спасибо @Clem. Я также попробовал этот подход, и я могу выдать тот же результат, что и другой ответ, но это не совсем то, что мне нужно. Я все еще борюсь с тем, как установить значение столбца ['before'] в текущей строке на основе значения в столбце ['after'] в строке выше.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню