【问题标题】:Apply a function to Pandas dataframe row by row (axis = 0) to create four new columns逐行(axis = 0)将函数应用于 Pandas 数据帧以创建四个新列
【发布时间】:2019-01-09 17:24:08
【问题描述】:

我一直在玩这个,但我什至无法让最简单的案例工作,所以我要寻求帮助。

我有一个大数据框,我正在尝试向其中添加四个新列。根据下面的 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) 创建列,但在这种情况下这不起作用,因为为了之前计算,我需要在同一行中计算之后。 IE。每一行都需要按顺序填充。这就是为什么我试图将其作为一个函数来处理,该函数接受行并计算四个新列的值。

如果有任何帮助或类似示例,我将不胜感激。谢谢。

编辑:我接受了 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]
          }

【问题讨论】:

  • 模组可以更改这篇文章的标题吗?当我第一次发布这个时我很困惑,现在它没有意义。需要更像:使用 .apply 填充熊猫数据框中的新列时跟踪和使用前一行的值

标签: python pandas dataframe


【解决方案1】:

这里有几个问题:

Before、Stake、After、Result 等应该是数字类型而不是字符串。所以改变它们 - 像这样:

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)

这是输出:

【讨论】:

  • 感谢@HakunaMaData,这是向前迈出的一大步。我能够复制此结果并对我在上面编辑的其他错误进行一些小的更改。但是,我希望 ['before'] 列的行为有所不同。结果应该是:100、100、101、94.95。您是否也可以提供任何指示?
  • 您可以使用全局变量来跟踪上一行的 after 值。另外..我无法达到 94.95.. 根据您提供的数据,我认为应该是 95.95。
【解决方案2】:

首先您需要更改您的功能,您将使用以下命令逐行应用: df.apply(lambda x: function(x,100,5), axis=1)

那么你的函数的签名将是:

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

小心!在这种情况下,您不是使用 apply() 操作数据框,而是使用一行操作,因此您必须在函数中调整您的代码。

希望这会有所帮助!

【讨论】:

  • 谢谢@Clem。我也尝试过这种方法,我可以产生与其他回复相同的输出,但这并不是我所追求的。我仍在苦苦思索如何根据上面行中 ['after'] 列中的值设置当前行中列 ['before'] 的值。
猜你喜欢
  • 2019-08-21
  • 1970-01-01
  • 1970-01-01
  • 2020-05-28
  • 2013-04-20
  • 2013-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多