Numpy python sum over vectors of different indices - python

I have the following formula:
that i have to code (C is a mtrix, y and y_star are vectors). I tried the following, according to this post: Python numpy array sum over certain indices
> def chisq02(y, y_star, C_inv):
> indices = len(y)
> return np.sum(np.sum(np.matmul(y[i] - y_star[i], np.matmul(C_inv, y[j]-y_star[j])) for i in indices)for j in indices)
but it returns me the error:
TypeError: 'int' object is not iterable
Obviously it does not work... Does anyone know how this could work ?

Your indices variable is just an integer, the length of y. But it must be a list from 0 to len(y) to loop over all indices. You can do this like so:
indices_list = range(len(y))
The range() function produces a list [0, 1, ..., len(y)-1]. Then you can loop over this list in the list comprehension.

If your matrices/vectors are not arrays, first convert them to arrays:
import numpy as np
y = np.array(y)
y_star = np.array(y_star)
C_inv = np.array(C_inv)
Use this, no need for loops:
def chisq02(y, y_star, C_inv):
return np.sum(np.matmul(np.matmul(y-y_star, C_inv), (y-y_star)))
If your y and y_star are vectors, simply this will work:
def chisq02(y, y_star, C_inv):
return np.matmul(np.matmul(y-y_star, C_inv), (y-y_star))

indices = len(y) returns you an integer, so to iterate you need to use for i in range(indices).
I suspect you don't need to use np.matmul in your case because you do scalar multiplication according to your formula. I suppose C_inv[i][j] should be used instead of C_inv.

Related

Why does np.linalg.solve give me an error when trying to solve a 16x16 system of equations?

I'm creating an nxn matrix with the largest value being n**n. np.linalg.solve works when n < 16, but for n >= 16, it gives an error:
numpy.core._exceptions.UFuncTypeError: Cannot cast ufunc 'solve1' input 0 from dtype('O') to dtype('float64') with casting rule 'same_kind'
Here's my code:
import numpy as np
def fib_to(n):
if n==0: return [0]
fibs = [0, 1]
for i in range(2, n+1):
fibs.append(fibs[-1] + fibs[-2])
return fibs
def get_nth_matrix(n):
coeficients = [[i**j for j in range(n, -1, -1)] for i in range(n+1)]
augment = fib_to(n)
return coeficients, augment
print(np.linalg.solve(*get_nth_matrix(16)))
I also noticed that doing np.linalg.cond on the matrix had the same problem. It worked for values up to 15, but gave a division by 0 error when n was 16 or greater
The list of lists returned by get_nth_matrix(16) contains integers that are too large to fit into numpy integer types. When you use np.linalg.solve() this list of lists gets converted into a numpy array, but because of this size issue, it produces an array of python objects. The error occurs since np.linalg.solve() can't handle this type of an array. You can replace the last line of get_nth_matrix() with
return np.array(coeficients, dtype=float), augment
to fix this - at least for the values that will not overflow the float type.

comparing numpy arrays element-wise setting an element-wise result

possibly this has been asked before, but I have a hard time finding a corresponding solution, since I can't find the right keywords to search for it.
One huge advantage of numpy arrays that I like is that they are transparent for many operations.
However in my code I have a function that has a conditional statement in the form (minimal working example):
import numpy as np
arr1 = np.array([1, 2, 3])
arr2 = np.array([1, 1, 3])
def func(x, y):
if x > y:
z = 1
else:
z = 2
return z
func(arr1, arr2) obviously results in an error message:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
I do understand what the problem here is and why it can't work like this.
What I would like to do here is that x > y is evaluated for each element and then an array z is returned with the corresponding result for each comparison. (Needs to ensure of course that the arrays are of equal length, but that's not a problem here)
I know that I could do this by changing func such that it iterates over the elements, but since I'm trying to improve my numpy skills: is there a way to do this without explicit iteration?
arr1 > arr2 does exactly what you'd hope it does: compare each element of the two arrays and build an array with the result. The result can be used to index in any of the two arrays, should you need to. The equivalent of your function, however, can be done with np.where:
res = np.where(arr1 > arr2, 1, 2)
or equivalently (but slightly less efficiently), using the boolean array directly:
res = np.ones(arr1.shape)
res[arr1 <= arr2] = 2 # note that I have to invert the condition to select the cells where you want the 2

Numpy - IF element is less than or equal to, then pass

I am trying to sort through a list of values in NUMPY / UPROOT, and I am having trouble with the formatting, as I am new to UPROOT.
The values are in some other list, and we'll call the values in one by one with a name, x.
If the values of x is greater than or equal to 5, I want to add it to the array, which is initially empty. If the number is less than 5, then we move onto the next number.
specifically, I need help with how to format the "greater than equal to"
array = []
if x is greater than or equal to 5:
array.append(x)
else:
return 0
Thanks everyone!
Using numpy you can do something like:
import numpy as np
# Initialize array
array = np.array([])
# Make some random values for x
x = np.floor(np.random.rand(10)*10)
for i in x: # Loop through x
if i >= 5: # If value is bigger or equal to 5
array = np.append(array, i) # add to array
So, "greater than equal to" is just >=
you're using a python list, which is different from numpy arrays. either way the following code should work
X = np.random.random(size= [10]) # array containing x values
if you want an numpy array
arr = X[X >= 5]
if you want a list
arr = list(X[X >= 5])

Bisection_method in array - numpy

I have an equation where my unknown is h and TR which is an array (2D).
I would like to solve the equation below by bisect method and as a result get a new array(2D), which will represent my h
Tpow,k,t - constant
h = np.empty_like(TR)
def f(h):
return (-TR+(Tpow-T1)*(1-exp((h**2*alfa*t)/k**2)*(1.0-erf(h*sqrt(alfa*t)/k))))
for i in range(len(TR)):
for j in range(len(TR[0])):
h[i][j] = scipy.optimize.bisect(f,0,600)
np.any() accepts a boolean array and returns a single boolean.
You are passing an array of floats, and then doing the comparison on the single boolean output. This is almost certainly not what you want. So instead of this:
if np.any(f(a)*f(b))>0:
do this:
if np.any(f(a) * f(b) > 0):
i.e., keep your comparisons inside np.any or np.all() Repeat for all the rest

fast way to get the indices of a lower triangular matrix as 1 dimensional list in python

Given the number of rows (or columns) , n, of a square matrix, I am trying to get the index pairs of the lower triangular matrix in a 1 dimensional list. So far I thought of the following solution:
def getLowerTriangularIndices(n):
inds=[];
for i in range(1,n):
for j in range(i):
inds.append((i,j))
return inds;
Considering the two for loops, it would be far better to have a more efficient way of calculating this maybe using numpy. Does anyone have a suggestion?
Numpy has a method for that...
import numpy as np
# create your matrix. If it's not yet a numpy array, make it one
ar = np.array(matrix)
indices = np.tril_indices_from(ar)
This returns a tuple of two arrays. If you want to have them as lists, you could do
indices = [list(x) for x in np.tril_indices_from(ar)]
You actually do not need to have an array to get the indices, there is also np.tril_indices, which takes the shape as arguments.
So your function would read:
def getLowerTriangularIndices(n):
return [list(x) for x in np.tril_indices(n)]
or if you want a list of tuples instead:
def getLowerTriangularIndices(n):
return zip(*np.tril_indices(n)]

Categories