How to apply a function for each element in a matrix in Python?
Question: I have a matrix of triangles where each line has 3 verticies: elementSet:

    
    
    Element Number      Vertices 
        2           473    1159   917
        3           271    1026   816
    

And I also have a matrix of nodes that assign a 2d coordinated for every
vertice nodeSet:

    
    
    Vertice Number                 (X,Y)
    917             5.487167292060809 2.195789288329368 
    271             5.448888739433895 2.38822856765269 
    

I've written some methods to handle the area calculation, they are contained
in a class:

    
    
      def findArea(self):
            self.elementsArea = nu.zeros((self.elementSet.shape[0],1))
            self.elementsArea[:] = self.calcArea(*self.elementSet[:,-3:])
    
      #Calculate the area of 3 points
      def calcArea (self,p1,p2,p3):
          [p1,p2,p3] = [self.nodeCoord(p1),self.nodeCoord(p2),self.nodeCoord(p3)]
    
          return 0.5*abs(p1[Xc]*(p2[Yc] - p3[Yc]) + p2[Xc]*(p3[Yc]-p1[Yc]) + p3[Xc]*(p1[Yc] - p2[Yc]))
    
    
      # returns the vertices of a point
      def nodeCoord(self, point):
            return(self.nodeSet[point-1,-3:-1]) 
    

where the function `calcArea` works fine but I want to apply a function to
every element of a matrix and assign to another matrix without using a loop.

I have to write something like:

    
    
    A[:] = func(B[:])
    

In `def findArea()` I tried to do something like this but it gives me the
following error:

    
    
    calcArea() takes 4 positional arguments but 2171 were given
    

I wanna use calcArea() to calculate the area passing arrays as arguments the
same way I did in this exemple:

    
    
    import numpy as np
    
    
    def test(x,y):
        return x*y
    
    f = np.array([[1,2,5,6,7] , [3,4,9,6,7] ,[6,7,23,34,32]])
    
    print(test(f[0,:],f[1,:]))
    

I am trying to apply calcArea method but I am getting now only a 2 dimmensions
array when I was suppose to get an array the same dimmension the original
vectors

    
    
    a.calcArea(f[0,:],f[1,:],f[2,:])
     array([ 7.5,  0. ])
    


Answer: If you can rearrange your data into a set of three 2D arrays containing the
_x,y_ coordinates for the first, second and third vertices of all your
triangles (e.g. with dimensions `(2, n)` where `n` is the number of triangles)
then you can easily vectorize the computation over all triangles:

    
    
    import numpy as np
    
    # adapted from your code. here p1, p2 and p3 are (2, ...) vectors of x,y coords.
    def triangle_area(p1, p2, p3):
          return 0.5 * np.abs(p1[0] * (p2[1] - p3[1]) +
                              p2[0] * (p3[1] - p1[1]) +
                              p3[0] * (p1[1] - p2[1]))
    
    n = 100000
    
    # some random vertex data
    vert_data = np.random.randn(3, 2, n)
    
    # each of these is a (2, n) vector of x,y coordinates
    P1, P2, P3 = vert_data
    
    # a 100000-long vector of areas
    areas = triangle_area(P1, P2, P3)
    

Timing:

    
    
    In [41]: %%timeit P1, P2, P3 = np.random.randn(3, 2, 100000)
       ....: triangle_area(P1, P2, P3)
       ....: 
    1000 loops, best of 3: 1.09 ms per loop
    

