Use of numpy fromfunction - python

im trying to use fromfunction to create a 5x5 matrix with gaussian values of mu=3 and sig=2, this is my attempt :
from random import gauss
import numpy as np
np.fromfunction(lambda i,j: gauss(3,2), (5, 5))
this is the result : 5.365244570434782
as i understand from the docs this should have worked, but i am getting a scalar instead of 5x5 matrix... why? and how to fix this?

The numpy.fromfunction docs are extremely misleading. Instead of calling your function repeatedly and building an array from the results, fromfunction actually only makes one call to the function you pass it. In that one call, it passes a number of index arrays to your function, instead of individual indices.
Stripping out the docstring, the implementation is as follows:
def fromfunction(function, shape, **kwargs):
dtype = kwargs.pop('dtype', float)
args = indices(shape, dtype=dtype)
return function(*args,**kwargs)
That means unless your function broadcasts, numpy.fromfunction doesn't do anything like what the docs say it does.

I know this is an old post, but for anyone stumbling upon this, the reason why it didn't work is, the expression inside lambda is not making use of the i, j variables
what you need could you achieved like this:
np.zeros((5, 5)) + gauss(3, 2)

Related

Creating a function in Python which runs over a range and returns a new value to an array each time

Basically, what I'm trying to create is a function which takes an array, in this case:
numpy.linspace(0, 0.2, 100)
and runs a lot of other code for each of the elements in the array and at the end creates a new array with one a number for each of the calculations for each element. A simple example would be that the function is doing a multiplication like this:
def func(x):
y = x * 10
return (y)
However, I want it to be able to take an array as an argument and return an array consisting of each y for each multiplication. The function above works for this, but the one I've tried creating for my code doesn't work with this method and only returns one value instead. Is there another way to make the function work as intended? Thanks for the help!
You could use this simple code:
def func(x):
y = []
for i in x:
y.append(i*10)
return y
Maybe take a look at np.vectorize:
https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.vectorize.html
np.vectorize can for example be used as a decorator:
#np.vectorize
def func(value):
...
return return_value
The function to be vectorized (here func) has to be a function,
that takes a value as input and returns a value.
This function then gets vectorized over the whole array.
It is mentioned in the documentation, but it cant hurt to emphasize it here:
In general this function is only used for convenience not for performance,
it is basically equivalent to using a for-loop.
If you are able to build up your function from numpys ufuncs like (np.add, np.mean, etc.) this will likely be much faster.
Or you could write your own:
https://docs.scipy.org/doc/numpy-1.13.0/reference/ufuncs.html
You can do this with numpy already with your function. For example, the code below will do what you want:
x = numpy.linspace(0, 0.2, 100)
y = x*10
If you defined x as above and passed it to your function it would perform exactly as you want.

apply a function to np.ndarray?

I have one numpy array, for instance a (a.shape = (2,20,50,50)). I would like to apply a function over its second axes.
My function is the difference between each elements only along the second axis, i.e.
res = a[:,i+1,:,:] - a[:,i,:,:] for i in range(20)
I have already tried it with lambda function, but the output is a list. I would like to have the result with the same shape as a. That means I want to have res.shape = (2,20,50,50).
I do appreciate that if someone guide me.
Thank you in advance.
You don't need to apply a function. Just subtract them directly.
res = a[:,1:,:,:]-a[:,0:-1,:,:]
Moreover, you won't get (2,20,50,50) ndarray but (2,19,50,50).

Calculating mean or median in one function in numpy

I have function that is supposed to compute, depending on user input, either the mean or median of a numpy.array. I have written it like this
import numpy as np
...
if input=='means':
return np.mean(matrix, axis=1)
if input=='median':
return np.median(matrix, axis=1)
But this seems kinda cumbersome. I figured there might be a standard numpy function that takes the array as well as the operation as input. I'm thinking something similar to R's tapply(X, Y, FUNCTION=Z) where Z can be any kind of function. But I could not find anything in the docs or on the Google...
Is there something like this in Numpy?
If there is no specific function, can someone think of a nice way of
doing this?
Thanks!
If your input string is mean instead of means, you could do:
return getattr(np, input)(matrix, axis=1)
Here the getattr call grabs the function you want from the numpy library. Then the second set of parentheses calls that function.
I don't think you need something specific to NumPy.
For example:
def myFunc(matrix, func, axis=1):
return func(matrix)
Then, to use the function:
import numpy as np
#Create random matrix (10, 10)
mat = np.random.randint(100, size=(10, 10))
print myFunc(mat, np.mean)

Use size in Python

I created a ndarray array in python
temp = np.array([1, 2, 3, 4])
To measure the length of this array, I can use
temp.size
or
np.size(temp)
both return 4. But I'm wondering what's the difference between the two expressions? Also, to get the lena image, I need to write
>>> import scipy.misc
>>> lena = scipy.misc.lena()
I'm wondering why there's a bracket pair after lena? Isn't lena a matrix? Something with () is like a function. I understand lena() is a function takes no inputs and returns a ndarray. I just feel like it's tedious to write this way.
In Matlab, it's quite clear to distinguish between a constant and a function. Function is defined and called with (), but constant (or pre-stored) can be called directly, e.g., "blobs.png"
np.size(temp) is a little more general than temp.size. At first glance, they appear to do the same thing:
>>> x = np.array([[1,2,3],[4,5,6]])
>>> x.size
6
>>> np.size(x)
6
This is true when you don't supply any additional arguments to np.size. But if you look at the documentation for np.size, you'll see that it accepts an additional axis parameter, which gives the size along the corresponding axis:
>>> np.size(x, 0)
2
>>> np.size(x, 1)
3
As far as your second question, scipy.misc.lena is a function as you point out. It is not a matrix. It is a function returning a matrix. The function (presumably) loads the data on the fly so that it isn't placed in memory whenever you import the scipy.misc module. This is a good thing, and actually not all that different than matlab.
temp.size is a property numpy.ndarray.size of ndarray where as numpy.size is a free function which calls the size property of ndarray or any other similar object which has the size method.
The reason numpy.size is flexible because it can act upon ndarray like object or objects that can be converted to ndarray
numpy.size also excepts an optional axis, along which it would calculate the size.
Here is the implementation of numpy.array.
def size(a, axis=None):
if axis is None:
try:
return a.size
except AttributeError:
return asarray(a).size
else:
try:
return a.shape[axis]
except AttributeError:
return asarray(a).shape[axis]

numpy ndarrays: row-wise and column-wise operations

If I wanted to apply a function row-wise (or column-wise) to an ndarray, do I look to ufuncs (doesn't seem like it) or some type of array broadcasting (not what I'm looking for either?) ?
Edit
I am looking for something like R's apply function. For instance,
apply(X,1,function(x) x*2)
would multiply 2 to each row of X through an anonymously defined function, but could also be a named function. (This is of course a silly, contrived example in which apply is not actually needed). There is no generic way to apply a function across an NumPy array's "axis", ?
First off, many numpy functions take an axis argument. It's probably possible (and better) to do what you want with that sort of approach.
However, a generic "apply this function row-wise" approach would look something like this:
import numpy as np
def rowwise(func):
def new_func(array2d, **kwargs):
# Run the function once to determine the size of the output
val = func(array2d[0], **kwargs)
output_array = np.zeros((array2d.shape[0], val.size), dtype=val.dtype)
output_array[0] = val
for i,row in enumerate(array2d[1:], start=1):
output_array[i] = func(row, **kwargs)
return output_array
return new_func
#rowwise
def test(data):
return np.cumsum(data)
x = np.arange(20).reshape((4,5))
print test(x)
Keep in mind that we can do exactly the same thing with just:
np.cumsum(x, axis=1)
There's often a better way that the generic approach, especially with numpy.
Edit:
I completely forgot about it, but the above is essentially equivalent to numpy.apply_along_axis.
So, we could re-write that as:
import numpy as np
def test(row):
return np.cumsum(row)
x = np.arange(20).reshape((4,5))
print np.apply_along_axis(test, 1, x)

Categories