Numpy broadcasting - using a variable value - python

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()

Related

Performing a certain operation on arrays in Python

I have two arrays I and X. I want to perform an operation which basically takes the indices from I and uses values from X. For example, I[0]=[0,1], I want to calculate X[0] and X[1] followed by X[0]-X[1] and append to a new array T. Similarly, for I[1]=[1,2], I want to calculate X[1] and X[2] followed by X[1]-X[2] and append to T. The expected output is presented.
import numpy as np
I=np.array([[0,1],[1,2]])
X=np.array([10,5,3])
The expected output is
T=array([[X[0]-X[1]],[X[1]-X[2]]])
The most basic approach is using nested indices together with the np.append() function.
It works like below:
T = np.append(X[I[0][0]] - X[I[0][1]], X[I[1][0]] - X[I[1][1]])
Where, X[I[0][0]] means to extract the value of I[0][0] and use that as the index we want for the array X.
You can also implement a loop to do that:
T = np.array([], dtype="int64")
for i in range(I.shape[0]):
for j in range(I.shape[1]-1):
T = np.append(T, X[I[i][j]] - X[I[i][j+1]])
If you find this answer helpful, please accept my answer. Thanks.
You can do this using integer array indexing. For large arrays, using for loops like in the currently accepted answer is going to be much slower than using vectorized operations.
import numpy as np
I = np.array([[0, 1], [1, 2]])
X = np.array([10, 5, 3])
T = X[I[:, 0:1]] - X[I[:, 1:2]]

Getting a single array containing several sub-arrays iteratively

I have a little question about python Numpy. What I want to do is the following:
having two numpy arrays arr1 = [1,2,3] and arr2 = [3,4,5] I would like to obtain a new array arr3 = [[1,2,3],[3,4,5]], but in an iterative way. For a single instance, this is just obtained by typing arr3 = np.array([arr1,arr2]).
What I have instead, are several arrays e.g. [4,3,1 ..], [4,3,5, ...],[1,2,1,...] and I would like to end up with [[4,3,1 ..], [4,3,5, ...],[1,2,1,...]], potentally using a for loop. How should I do this?
EDIT:
Ok I'm trying to add more details to the overall problem. First, I have a list of strings list_strings=['A', 'B','C', 'D', ...]. I'm using a specific method to obtain informative numbers out of a single string, so for example I have method(list_strings[0]) = [1,2,3,...], and I can do this for each single string I have in the initial list.
What I would like to come up with is an iterative for loop to end up having all the numbers extracted from each string in turn in the way I've described at the beginning, i.e.a single array with all the numeric sub-arrays with information extracted from each string. Hope this makes more sense now, and sorry If I haven't explained correctly, I'm really new in programming and trying to figure out stuff.
Well if your strings are in a list, we want to put the arrays that result from calling method in a list as well. Python's list comprehension is a great way to achieve that.
list_strings = ['A', ...]
list_of_converted_strings = [method(item) for item in list_strings]
arr = np.array(list_of_converted_strings)
Numpy arrays are of fixed dimension i.e. for example a 2D numpy array of shape n X m will have n rows and m columns. If you want to convert a list of lists into a numpy array all the the sublists in the main list should be of same length. You cannot convert it into a numpy array if sublist are of varying size.
For example, below code will give an error
np.array([[1], [3,4]]])
so if all the sublist are of same size then you can use
np.array([method(x) for x in strings]])

how to populate a numpy 2D array with function returning a numpy 1D array

I have function predicton like
def predictions(degree):
some magic,
return an np.ndarray([0..100])
I want to call this function for a few values of degree and use it to populate a larger np.ndarray (n=2), filling each row with the outcome of the function predictions. It seems like a simple task but somehow I cant get it working. I tried with
for deg in [1,2,4,8,10]:
np.append(result, predictions(deg),axis=1)
with result being an np.empty(100). But that failed with Singleton array array(1) cannot be considered a valid collection.
I could not get fromfunction it only works on a coordinate tuple, and the irregular list of degrees is not covered in the docs.
Don't use np.ndarray until you are older and wiser! I couldn't even use it without rereading the docs.
arr1d = np.array([1,2,3,4,5])
is the correct way to construct a 1d array from a list of numbers.
Also don't use np.append. I won't even add the 'older and wiser' qualification. It doesn't work in-place; and is slow when used in a loop.
A good way of building a 2 array from 1d arrays is:
alist = []
for i in ....:
alist.append(<alist or 1d array>)
arr = np.array(alist)
provided all the sublists have the same size, arr should be a 2d array.
This is equivalent to building a 2d array from
np.array([[1,2,3], [4,5,6]])
that is a list of lists.
Or a list comprehension:
np.array([predictions(i) for i in range(10)])
Again, predictions must all return the same length arrays or lists.
append is in the boring section of numpy. here you know the shape in advance
len_predictions = 100
def predictions(degree):
return np.ones((len_predictions,))
degrees = [1,2,4,8,10]
result = np.empty((len(degrees), len_predictions))
for i, deg in enumerate(degrees):
result[i] = predictions(deg)
if you want to store the degree somehow, you can use custom dtypes

Numpy array of multiple indices replace with a different matrix

I have an array of 2d indices.
indices = [[2,4], [6,77], [102,554]]
Now, I have a different 4-dimensional array, arr, and I want to only extract an array (it is an array, since it is 4-dimensional) with corresponding index in the indices array. It is equivalent to the following code.
for i in range(len(indices)):
output[i] = arr[indices[i][0], indices[i][1]]
However, I realized that using explicit for-loop yields a slow result. Is there any built-in numpy API that I can utilized? At this point, I tried using np.choose, np.put, np.take, but did not succeed to yield what I wanted. Thank you!
We need to index into the first two axes with the two columns from indices (thinking of it as an array).
Thus, simply convert to array and index, like so -
indices_arr = np.array(indices)
out = arr[indices_arr[:,0], indices_arr[:,1]]
Or we could extract those directly without converting to array and then index -
d0,d1 = [i[0] for i in indices], [i[1] for i in indices]
out = arr[d0,d1]
Another way to extract the elements would be with conversion to tuple, like so -
out = arr[tuple(indices_arr.T)]
If indices is already an array, skip the conversion process and use indices in places where we had indices_arr.
Try using the take function of numpy arrays. Your code should be something like:
outputarray= np.take(arr,indices)

Extend numpy array in a way compatible with builtin arrays

I am trying to write code that would not depend on whether the user uses np.array or a builtin array. I am trying to avoid checking object types, etc. The only problem that I have is in extending arrays. For example, if I have two Python arrays, a and b, to extend the first by the second, I can either do a = a + b, or a.extend(b). On the other hand, if a is a numpy array, I need to use np.append or something else.
Is there a quick way to extend arrays independently of whether they are np arrays or Python arrays?
NumPy's append() works on lists too!
>>> np.append([1,2,3], [1,2,3])
array([1, 2, 3, 1, 2, 3])
If you want to automatically make the result be the same type as the input, try this:
mytype = type(a)
arr = np.append(a, b)
result = mytype(arr)
Even if your function is flexible on input, your output should be of specific type. So I would just convert to desired output type.
For example, if my functions is working with numpy.array and returns a numpy.array, but I want to allow lists to be input as well, the first thing I would do is convert lists to numpy.arrays.
Like this:
def my_func(a, b):
a = np.asarray(a)
b = np.asarray(b)
# do my stuff here

Categories

Resources