适用于整个数据帧的用户定义函数涉及pandas中的另一个数据帧

时间:2015-02-03 04:47:06

标签: python performance numpy pandas dataframe

我正在尝试在两个数据帧df1和df2之间进行一些数学运算,但我发现很难使用pd.apply函数:

DF1:

   number1  number2  number3  … 
0   0         0        0      …
1   0         0.25     0      …
2   0.1       0.1      0      …
3   0         0        0.3    …
4   0         0        0      … 

DF2:

   number1  number2  number3    … 
0   2         3.3        6      …
1   2.1       3.4        6      …
2   2.2       3.2      5.8      …
3   2.1       3.4      6.2      …
4   2         4.0      6.4      … 

我想按照以下规则更改df1中的每个元素:

  1. 将df1中的每0个元素更改为1
  2. df1中的每个非零元素,让df.iloc [m,n] =(1-df.iloc [m,n])/ df2.shift(1).iloc [m,n],其中m ,n是非零元素的位置
  3. 现在我有一个有效的代码:

    df1_new=pd.DataFrame(1,index = df1.index,columns = df1.columns)
    df2_sft=df2.shift(1)
    m,n=np.where(np.array(df1)!=0)
    for i in m:
      for j in n:
        df1_new.iloc[i,j]=(1-df1.iloc[i,j])/df2_sft.iloc[i,j]
    

    但正如你所看到的,如果df1和df2很大,它只是丑陋且极其缓慢。我相信必须有很多其他方法可以很快地完成这个简单的数学运算,希望你能给予一些帮助。

    另外,我总是对apply和applymap感到困惑,有什么区别,何时应该使用另一个?

1 个答案:

答案 0 :(得分:3)

你想要对代码进行矢量化,也就是说,而不是使用for循环来对整个DataFrame /数组进行计算,类似下面的代码会快得多:

In [11]: ((1 - df1) / df2_sft).where(df1 != 0, 1)
Out[11]:
    number1   number2  number3
0  1.000000  1.000000  1.00000
1  1.000000  0.227273  1.00000
2  0.428571  0.264706  1.00000
3  1.000000  1.000000  0.12069
4  1.000000  1.000000  1.00000

注意:这与您的代码不匹配,因为您(错误地)不会仅仅迭代非零元素(当您迭代所有项目时) m代表n中的每个元素,而不是压缩的项目。