【问题标题】:apply to the entire dataframe a user-defined function involving another dataframe in pandas将用户定义的函数应用于整个数据框,该函数涉及熊猫中的另一个数据框
【发布时间】:2015-04-02 05:08:38
【问题描述】:

我正在尝试在两个数据帧 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是非零元素的位置

现在我有一个有效的代码:

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 感到困惑,有什么区别,什么时候应该使用一个而不是另一个?

【问题讨论】:

    标签: python performance numpy pandas dataframe


    【解决方案1】:

    你想对你的代码进行矢量化,也就是说,而不是使用 for 循环对整个 DataFrame/array 进行计算,如下所示会快得多:

    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 中,而不是压缩的项目)。

    【讨论】:

    • 以前从未使用过'where',非常感谢!还有其他方法吗?也许使用应用?
    • @user6396 apply 不会像矢量化或使用 where 那样高效/快速,因为基本上它必须像在示例代码中那样在 python 中循环(而不是使用更快的 numpy/ C)。
    猜你喜欢
    • 2018-11-13
    • 1970-01-01
    • 1970-01-01
    • 2013-08-10
    • 2017-08-23
    • 1970-01-01
    • 1970-01-01
    • 2021-10-12
    相关资源
    最近更新 更多