我有一只熊猫dataframe
。我想基于多个列输入生成一个新的变量(列),其中年份索引大于某个值。
下面的例子说明了我想要做的事情,但是我想把它简化成一个函数,因为实际的计算比下面的例子更复杂,变量名也更长。
理想情况下,该函数会将计算拆分为中间临时值(不保存到df
)并跨多行以使其更易于阅读。例如,可以定义:Share = (df['B']+df['C']) / (df['B']+df['C']+df['D'])
,然后是X = A + Share * E
。
我以前使用apply
将函数应用于dataframe
,但该示例仅使用单个变量作为输入,没有where子句,我不知道如何扩展示例。
我如何简单地根据A
、B
、C
、D
和E
生成X
,其中year
>= 2020?
import numpy as np
import pandas as pd
np.random.seed(2981)
df = pd.DataFrame({
'year' : [2018, 2019, 2020, 2021,2018, 2019, 2020, 2021,2018, 2019, 2020, 2021],
'id' : ['ABC','ABC','ABC','ABC','DEF','DEF','DEF','DEF','GHI','GHI','GHI','GHI'],
'A': np.random.choice(range(100),12),
'B': np.random.choice(range(100),12),
'C': np.random.choice(range(100),12),
'D': np.random.choice(range(100),12),
'E': np.random.choice(range(100),12),
})
df = df.set_index('year')
df['X'] = np.where( df.index >= 2020, df['A'] + (df['B']+df['C']) / (df['B']+df['C']+df['D']) * df['E'] , np.nan )
首先,您应该只在必要时使用apply。向量化函数会快得多,你现在用np来写它的方式。Where语句使用了这些。如果您真的想让代码更具可读性(以(可能很小的)时间和内存为代价),您可以创建一个中间列,然后在np中使用它。声明的地方。
df["Share"] = ( df.B + df.C ) / ( df.B + df.C + df.D )
df["X"] = ( df.A + df.Share * df.E ).where( df.index >= 2020 )
要回答您的问题,您可以创建一个自定义函数,然后将其应用于您的DataFrame。
def my_func( year,a,b,c,d,e ):
#This function can be longer and do more things
return np.nan if year < 2020 else a + ( ( (b + c) / (b + c + d) ) * e )
df['X'] = df.apply( lambda x: my_func( x.name, x.A, x.B, x.C, x.D, x.E ), axis = 1 )
注意,当使用apply和axis = 1
时,要访问行索引,您需要使用name属性。
此外,由于应用函数相对较慢,因此值得创建一些列来处理一些中间步骤(例如将几个列相加等),这样就不需要在每次迭代中完成这些步骤。
查看这个答案以获得更多应用自定义函数的示例。