0

Related to this question:

I have the following code with custom functions:

import numpy as np
from scipy.integrate import quad
from scipy.special import binom
from scipy.stats import norm
import math as mt
ranks = np.array([[8, 5, 3, 7, 6, 2, 1, 4],
       [8, 5, 3, 7, 6, 2, 1, 4]])

def E(r, n):
    print(r,n)
    def f(x):
        F = Phi(x)
        return x*(1-F)**(r-1)*F**(n-r)*phi(x)
    return -r*binom(n, r)*quad(f, -inf, inf)[0]

I want to apply the function E over each row of the array ranks.

I tried np.apply_along_axis but the problem I'm having is that I have 2 arguments for the function: the individual rank of an element in a row of an array (r) and the length of that row (n).

Also, I'm wondering if it would be faster and better anyway to use map as with the accepted answer to the question referenced above (because speed is important with this).

Here's what I've tried:

result = np.apply_along_axis(E, 1, ranks)

Issue: I need to provide the n argument. Also, this may be slower than mapping.

#not sure if the "*" is needed or what it does.
def E2(i):
    return [*E(ranks[i], len(ranks[i]))]

it = 2 #2 rows (iterations)
indx = np.arange(it)
result = np.array(list(map(E2, indx))) 

Issue: Needs 1 rank at a time, per row. Not sure how to achieve this.

Thanks in advance!

Dance Party
  • 3,459
  • 10
  • 42
  • 67
  • If I understand you correctly, n is `len(r)`, so it's superfluous to pass that information. It should be just calculated in the fuction internally. – Reti43 Feb 15 '21 at 05:03
  • `apply_along_axis` is **not** a speed tool. It may be convenient when iterating over 2 or more dimensions (of a 3d+ array), but it does not make the iteration faster. If it isn't convenient to use, forget it. I prefer list comprehension over map for its expresiveness. – hpaulj Feb 15 '21 at 05:15
  • @Reti43 I'm open to trying that, but it would mean I'd need to pass each element of the row and the row itself to the function for each value of the row. – Dance Party Feb 15 '21 at 15:45

1 Answers1

0

Since you haven't specified the imports for Phi, quad etc, I won't try to provide a working example.

def E(r, n):
    print(r,n)
    def f(x):
        F = Phi(x)
        return x*(1-F)**(r-1)*F**(n-r)*phi(x)
    return -r*binom(n, r)*quad(f, -inf, inf)[0]

A simple list comprehension:

res = [E(r,n) for r in ranks]

I'd prefer to move the f(x) definition out of E. That may be more of a matter of style than performance.

def f(x,r):
    F = Phi(x)
    return x*(1-F)**(r-1)*F**(n-r)*phi(x)

def E(r,n):
    temp = quad(f, -inf, inf, args=(r,))[0]
    return -r*binom(n, r)*temp
hpaulj
  • 221,503
  • 14
  • 230
  • 353