python store function in array - python

N00b question, maybe.
I am new-ish to python, but I was wondering if it is possible to store a function in an array? I want to do an array multiplication, where the value of one array is multiplied by a function on a location of another array of functions. Or actually, the value of the first array is inserted in the function of the designated location. This should create a new array where the values are an outcome of the "multiplication".
>>> import numpy as np
>>> a = [[1, 0], [0, 1]]
>>> b = [[f(x), g(x)], [(h(x), f(x)]]
>>> np.dot(a, b)
array([[0, 1],
[2, 0]])
Assuming that f(x), g(x) and h(x) are defined functions. In this case python will say that x is not defined. So far I know. However, I do not want to say, for example, f(a[0][1]), because I want to reuse array b and also be able to put the functions on random locations in the array.
In short I detect three questions:
- Is there a known way to have an array where the values are functions?
- If not, should I redefine an array function or write a new class for this? (how do I attack this problem?)
- If it is possible to create an array of functions, can I fill the 'function values' dynamically in the array (populate the array dynamically with functions) or can it only be static values?
like for example
b[0]=f(x)
And yes, I really want to do this with python.

f(x) is not a function (even in mathematics). The function is f. In python there is no problem to store functions in array:
def my_func():
print("Foo")
my_other_func = lambda: print("Bar")
my_arr = [my_func, my_other_func]

Your example puts the result of calling a function into your array.
b[0] = f
actually puts the function itself into the array, so that
b[0](x)
would have the same effect as
f(x)

Is there a known way to have an array where the values are functions?
There is, as stated by others already.
def my func(x):
return x
my_other_func = lambda x: x
l = [my_func, my_other_func]
If not, should I redefine an array function or write a new class for this? (how do I attack this problem?)
Not relevant
If it is possible to create an array of functions, can I fill the 'function values' dynamically in the array (populate the array dynamically with functions) or can it only be static values?
The 'function values' are called parameters and can be assigned after having the function in the array:
a[0](5) # == my_func(5)
a[1]('Hello') # == my_other_func('Hello')
The problem is that you are trying to use matrix multiplication as parameter passing and that will not work, you could create a helper fucntion that does it.
def callByElements(parameterMatrix, functionMatrix):
rows = len(parameterMatrix)
cols = len(parameterMatrix[0])
result = np.zeros( (rows, cols) )
for i in range(rows):
for j in range(cols):
result[i,j] = functionMatrix[i,j](parameterMatrix[i,j])
return result

Related

Python : equivalent of Matlab ismember on rows for large arrays

I can't find an efficient way to conduct Matlab's "ismember(a,b,'rows')" with Python where a and b are arrays of size (ma,2) and (mb,2) respectively and m is the number of couples.
The ismember module (https://pypi.org/project/ismember/) crashes because at some point i.e. when doing np.all(a[:, None] == b, axis=2).any(axis=1) it needs to create an array of size (ma,mb,2) and it is too big. Moreover, even when the function works (because arrays are small enough), it is about a 100times slower than in Matlab. I guess it is because Matlab uses a built-in mex function. Why python does not have what I would think to be such an important function ? I use it countless times in my calculations...
ps : the solution proposed here Python version of ismember with 'rows' and index does not correspond to the true matlab's ismember function since it does not work element by element i.e. it does not verify that a couple of values of 'a' exists in 'b' but only if values of each column of 'a' exist in each columns of 'b'.
You can use np.unique(array,axis=0) in order to find the identical row of an array. So with this function you can simplify your 2D problem to a 1D problem which can be easily solve with np.isin():
import numpy as np
# Dummy example array:
a = np.array([[1,2],[3,4]])
b = np.array([[3,5],[2,3],[3,4]])
# ismember_row function, which rows of a are in b:
def ismember_row(a,b):
# Get the unique row index
_, rev = np.unique(np.concatenate((b,a)),axis=0,return_inverse=True)
# Split the index
a_rev = rev[len(b):]
b_rev = rev[:len(b)]
# Return the result:
return np.isin(a_rev,b_rev)
res = ismember_row(a,b)
# res = array([False, True])

Numpy broadcasting - using a variable value

EDIT:
As my question was badly formulated, I decided to rewrite it.
Does numpy allow to create an array with a function, without using Python's standard list comprehension ?
With list comprehension I could have:
array = np.array([f(i) for i in range(100)])
with f a given function.
But if the constructed array is really big, using Python's list would be slow and would eat a lot of memory.
If such a way doesn't exist, I suppose I could first create an array of my wanted size
array = np.arange(100)
And then map a function over it.
array = f(array)
According to results from another post, it seems that it would be a reasonable solution.
Let's say I want to use the add function with a simple int value, it will be as follows:
array = np.array([i for i in range(5)])
array + 5
But now what if I want the value (here 5) as something that varies according to the index of the array element. For example the operation:
array + [i for i in range(5)]
What object can I use to define special rules for a variable value within a vectorized operation ?
You can add two arrays together like this:
Simple adding two arrays using numpy in python?
This assumes your "variable by index" is just another array.
For your specific example, a jury-rigged solution would be to use numpy.arange() as in:
In [4]: array + np.arange(5)
Out[4]: array([0, 2, 4, 6, 8])
In general, you can find some numpy ufunc that does the job of your custom function or you can compose then in a python function to do so, which then returns an ndarray, something like:
def custom_func():
# code for your tasks
return arr
You can then simply add the returned result to your already defined array as in:
array + cusom_func()

How to concatenate an empty array with Numpy.concatenate?

I need to create an array of a specific size mxn filled with empty values so that when I concatenate to that array the initial values will be overwritten with the added values.
My current code:
a = numpy.empty([2,2]) # Make empty 2x2 matrix
b = numpy.array([[1,2],[3,4]]) # Make example 2x2 matrix
myArray = numpy.concatenate((a,b)) # Combine empty and example arrays
Unfortunately, I end up making a 4x2 matrix instead of a 2x2 matrix with the values of b.
Is there anyway to make an actually empty array of a certain size so when I concatenate to it, the values of it become my added values instead of the default + added values?
Like Oniow said, concatenate does exactly what you saw.
If you want 'default values' that will differ from regular scalar elements, I would suggest you to initialize your array with NaNs (as your 'default value'). If I understand your question, you want to merge matrices so that regular scalars will override your 'default value' elements.
Anyway I suggest you to add the following:
def get_default(size_x,size_y):
# returns a new matrix filled with 'default values'
tmp = np.empty([size_x,size_y])
tmp.fill(np.nan)
return tmp
And also:
def merge(a, b):
l = lambda x, y: y if np.isnan(x) else x
l = np.vectorize(l)
return map(l, a, b)
Note that if you merge 2 matrices, and both values are non 'default' then it will take the value of the left matrix.
Using NaNs as default value, will result the expected behavior from a default value, for example all math ops will result 'default' as this value indicates that you don't really care about this index in the matrix.
If I understand your question correctly - concatenate is not what you are looking for. Concatenate does as you saw: joins along an axis.
If you are trying to have an empty matrix that becomes the values of another you could do the following:
import numpy as np
a = np.zeros([2,2])
b = np.array([[1,2],[3,4]])
my_array = a + b
--or--
import numpy as np
my_array = np.zeros([2,2]) # you can use empty here instead in this case.
my_array[0,0] = float(input('Enter first value: ')) # However you get your data to put them into the arrays.
But, I am guessing that is not what you really want as you could just use my_array = b. If you edit your question with more info I may be able to help more.
If you are worried about values adding over time to your array...
import numpy as np
a = np.zeros([2,2])
my_array = b # b is some other 2x2 matrix
''' Do stuff '''
new_b # New array has appeared
my_array = new_b # update your array to these new values. values will not add.
# Note: if you make changes to my_array those changes will carry onto new_b. To avoid this at the cost of some memory:
my_array = np.copy(new_b)

Zip function in python 3.2.3 not working as hoped

I am trying to define a function that transposes a matrix. This is my code:
def Transpose (A):
B = list(zip(*A))
return B
Now when I call the function somewhere in the program like such:
Matrix = [[1,2,3],[4,5,6],[7,8,9]]
Transpose(Matrix)
print(Matrix)
The matrix comes out unchanged. What am I doing wrong?
Your function returns a new value that does not affect your matrix (zip does not change it's parameters). You are not doing anything wrong, that is the correct way of doing things.
Just change it to:
print(Transpose(Matrix))
or
Matrix = Transpose(Matrix)
Note: You really should be using lower-case names for your functions and variables.

How to represent matrices in python

How can I represent matrices in python?
Take a look at this answer:
from numpy import matrix
from numpy import linalg
A = matrix( [[1,2,3],[11,12,13],[21,22,23]]) # Creates a matrix.
x = matrix( [[1],[2],[3]] ) # Creates a matrix (like a column vector).
y = matrix( [[1,2,3]] ) # Creates a matrix (like a row vector).
print A.T # Transpose of A.
print A*x # Matrix multiplication of A and x.
print A.I # Inverse of A.
print linalg.solve(A, x) # Solve the linear equation system.
Python doesn't have matrices. You can use a list of lists or NumPy
If you are not going to use the NumPy library, you can use the nested list. This is code to implement the dynamic nested list (2-dimensional lists).
Let r is the number of rows
let r=3
m=[]
for i in range(r):
m.append([int(x) for x in raw_input().split()])
Any time you can append a row using
m.append([int(x) for x in raw_input().split()])
Above, you have to enter the matrix row-wise. To insert a column:
for i in m:
i.append(x) # x is the value to be added in column
To print the matrix:
print m # all in single row
for i in m:
print i # each row in a different line
((1,2,3,4),
(5,6,7,8),
(9,0,1,2))
Using tuples instead of lists makes it marginally harder to change the data structure in unwanted ways.
If you are going to do extensive use of those, you are best off wrapping a true number array in a class, so you can define methods and properties on them. (Or, you could NumPy, SciPy, ... if you are going to do your processing with those libraries.)

Categories

Resources