I'm working on the problem which asks me:
Add two NumPy vectors or matrices together, if possible. If it is not possible to add the two vectors/matrices together (because their sizes differ), return False.
Here is my approach:
import numpy as np
def mat_addition(A, B):
if A.shape != B.shape:
return False
else:
return np.sum(A,B)
But when I run the code for testing, it says
TypeError: only integer scalar arrays can be converted to a scalar index
Can someone tell me what's wrong with my code?
np.sum can in fact be used in the way you want. You just need to wrap the arguments you pass to np.sum in a list:
import numpy as np
def mat_addition(A, B):
if A.shape != B.shape:
return False
else:
return np.sum([A,B])
a = np.arange(5*3).reshape(5,3)
b = np.arange(5*3, 5*3*2).reshape(5,3)
print(mat_addition(a,b))
Output:
435
As per the numpy.sum docs, this function expects a single "array_like" object as its first argument. A list of arrays is a perfectly valid "array_like" object, so the above code works.
Related
I am trying to use scipy.ndimage.generic_filter1d for the first time, but it's not going well. Here's what I'm trying
import numpy as np
from scipy.ndimage import generic_filter1d
def test(x):
return x.sum()
im_cube = np.zeros((100,100,100))
calc = generic_filter1d(im_cube, test, filter_size=5, axis=2)
But I get this error:
TypeError: test() takes 1 positional argument but 2 were given
I'm using scipy 1.4.1 What am I doing wrong?
For the function, I also tried np.mean but then I got this:
TypeError: only integer scalar arrays can be converted to a scalar index
According to the documentation, the callback accepts two arguments: a reference to the input line, and a reference to the output line. It does not return the output, but rather modifies the provided buffer in-place.
If you want to implement a rolling sum filter, you will need to do that somewhat manually. For example:
def test(x, out)
out[:] = np.lib.stride_tricks.as_strided(x, strides=x.strides * 2, shape=(5, x.size - 4)).sum(axis=0)
To make it a mean, add / 5 at the end.
The purpose of genetic_filter1d is to format the edges and run the outer loop. It does not actually implement the rolling filter for you. You are still required to implement the entire inner loop yourself.
epsData is a two-dimensional array consisting of Dates and StockID.
I took out some of the code in order to make it simple.
The code calls the functions Generate and neweps, epsData is passed by the engine. I am not sure why it gives an error when I try to pass the array epsss to the SUE() function.
I tried to remove the extra bracket in array (if any) by using flatten function but that does not help.
SUE() is supposed to loop through the array and find the 4th last different value and then store these in an array.
I get this error:
TypeError: return arrays must be of ArrayType
with the three lines marked below:
def lastdifferentvalue(vals,datas,i):
sizes=len(datas)
j=sizes-1
values=0
while (i>0) and (j>=0):
if logical_and((vals-datas[j]!=0),(datas[j]!=0),(datas[j-1]!=0)): # !! HERE !!
i=i-1
values=datas[j-1]
j=j-1
return j, values
def SUE(datas):
sizes=len(datas)
j=sizes-1
values=0
sues=zeros(8)
eps1=datas[j]
i=7
while (j>0) and (i>=0) :
counts, eps2=lastdifferentvalue(eps1,array(datas[0:j]),4)
if eps2!=0:
sues[i]=eps1-eps2
i=i-1
j,eps1=lastdifferentvalue(eps1,datas[0:j],1) # !! HERE !!
stddev=std(SUE)
sue7=SUE[7]
return stddev,sue7
def Generate(di,alpha):
#the code below loops through the data. neweps is a two dimensional array of floats [dates, stockid]
for ii in range(0,len(alpha)):
if (epss[2,ii]-epss[1,ii]!=0) and (epss[2,ii]!=0) and (epss[1,ii]!=0):
predata=0
epsss= neweps[di-delay-250:di-delay+1,ii]
stddevs,suedata= SUE(array(epsss.flatten())) # !! HERE !!
Presumably, you're using numpy.logical_and, in the form of
np.logical_and(a, b, c)
with the meaning that you'd like to take the logical and of the three. If you check the documentation, though, that's not what it does. It's interpreting c as the array where you intend to store the results.
You probably mean here something like
np.logical_and(a, np.logical_and(b, c))
or
from functools import reduce
reduce(np.logical_and, [a, b, c])
The line:
if logical_and((vals-datas[j]!=0),(datas[j]!=0),(datas[j-1]!=0))
has two errors:
Presumably you are wanting to perform a logical_and over (vals-datas[j] != 0) and (datas[j] != 0) and (datas[j-1] != 0). However numpy.logical_and only takes two input parameters, the third if passed is assumed to be an output array. Thus if you are wishing to have numpy.logical_and operate over three arrays it should be expressed as:
logical_and(logical_and((vals-datas[j] != 0), (datas[j] != 0)), (datas[j-1] != 0))
In any case, using a logical_and in an if statement makes no sense. It returns an array and an array does not have a truth value. That is, the result of a logical_and is an array of booleans, some of which are true and some false. Are you wishing to check if they are all true? Or if at least some are true?
If the former, then you should test it as:
if numpy.all(logical_and(...)):
...
And if the latter then test it as:
if numpy.any(logical_and(...)):
...
I would like to apply a function to every element of a numpy.ndarray, something like this:
import numpy
import math
a = numpy.arange(10).reshape(2,5)
b = map(math.sin, a)
print b
but this gives:
TypeError: only length-1 arrays can be converted to Python scalars
I know I can do this:
import numpy
import math
a = numpy.arange(10).reshape(2,5)
def recursive_map(function, value):
if isinstance(value, (list, numpy.ndarray)):
out = numpy.array(map(lambda x: recursive_map(function, x), value))
else:
out = function(value)
return out
c = recursive_map(math.sin, a)
print c
My question is: is there a built-in function or method to do this? It seems elementary, but I haven't been able to find it. I am using Python 2.7.
Use np.sin it works element wise on ndarray already.
You can also reshape to a 1D array and the native map should just work. Then you can use reshape again to restore the original dimensions.
You can also use np.vectorize to write functions that can work like np.sin.
I wonder if anyone has an elegant solution to being able to pass a python list, a numpy vector (shape(n,)) or a numpy vector (shape(n,1)) to a function. The idea would be to generalize a function such that any of the three would be valid without adding complexity.
Initial thoughts:
1) Use a type checking decorator function and cast to a standard representation.
2) Add type checking logic inline (significantly less ideal than #1).
3) ?
I do not generally use python builtin array types, but suspect a solution to this question would also support those.
I think the simplest thing to do is to start off your function with numpy.atleast_2d. Then, all 3 of your possibilities will be converted to the x.shape == (n, 1) case, and you can use that to simplify your function.
For example,
def sum(x):
x = np.atleast_2d(x)
return np.dot(x, np.ones((x.shape[0], 1)))
atleast_2d returns a view on that array, so there won't be much overhead if you pass in something that's already an ndarray. However, if you plan to modify x and therefore want to make a copy instead, you can do x = np.atleast_2d(np.array(x)).
You can convert the three types to a "canonical" type, which is a 1dim array, using:
arr = np.asarray(arr).ravel()
Put in a decorator:
import numpy as np
import functools
def takes_1dim_array(func):
#functools.wraps(func)
def f(arr, *a, **kw):
arr = np.asarray(arr).ravel()
return func(arr, *a, **kw)
return f
Then:
#takes_1dim_arr
def func(arr):
print arr.shape
Suppose you have an array of two arrays. How can you make a function correctly separate the parts and apply the lambda function here on each of them?
import numpy as np
a=np.asarray([[1]])
b=np.asarray([[1,2]])
r=np.asarray([a,b])
f=lambda x,y:x[:,0]+y
print f(*r)
This code will rise: IndexError: too many indices. However simple change of a two a (1,2) array will change everything since numpy makes r an ndarray and correctly apply function to each of a and b. I understand this is because that what f gets for its first argument is [array([[1]])] but not [[1]]. Is there any way to generate the same behaviour in the first case as well?
import numpy as np
a=np.asarray([[1,2]])
b=np.asarray([[1,3]])
r=np.asarray([a,b])
f=lambda x,y:x[:,0]+y
print f(*r)
With output:
[[2 4]]
EDIT: Just to clarify since f will be called in my real code for million times and its more complex its important for me to keep this procedure as efficient as possible. Thanks.
You need to make a asobjectarray() function:
import numpy as np
def asobjectarray(alist):
r = np.ndarray(len(alist), object)
r[:] = alist
return r
a = np.asarray([[1]])
b = np.asarray([[1,2]])
r = asobjectarray([a,b])
f=lambda x,y:x[:,0]+y
print f(*r)