Suppose i have a (list | np.array) a of size (N,) and a (list | np.array) l of integers between 0 and N-1.
Is there a way i could write more efficiently sum([a[x] for x in l]) ?
Four different conditions:
a is a numpy array, l is a numpy array
a is a numpy array, l is a list
a is a list, l is a numpy array
a is a list, l is a list
a is a numpy array, l is a numpy array
a is a numpy array, l is a list
For both of the above you can do a[l].sum()
a is a list, l is a numpy array
a is a list, l is a list
For these last two, your options are either to cast a to numpy and then do as above:
np.asarray(a)[l].sum()
or if you are going to use something like your list comprehension, then at least use a generator expression instead - there is no need to build a list simply to add up the values:
sum(a[x] for x in l)
If you are looking for a single solution that you can use regardless of the type, then np.asarray(a)[l].sum() (as suggested above) will work, because if the argument to np.asarray is an array anyway, then it will simply use it as-is -- but be aware that if a is a list then this will need to create an array version of a, so use of the generator expression will be more economical on memory.
import numpy as np
a_list = [10, 11, 12]
l_list = [2, 2]
a_array = np.array(a_list)
l_array = np.array(l_list)
for a in a_list, a_array:
for l in l_list, l_array:
print(np.asarray(a)[l].sum())
gives:
24
24
24
24
Related
I want to check whether a 1D numpy array in the list of a 1D numpy arrays and None for an if condition.
I did it like this:
arr = np.array([1,2])
lst = [np.array([1,2]), np.array([3,4]), None, None]
if list(arr) in [list(i) for i in lst if i is not None]:
print("Yes")
else:
print("No")
but the size of the list and the numpy array can be much larger, so is there a more efficient way to do this? instead of changing every numpy array to list.
You cannot avoid one iteration through the lst to modify its elements (numpy arrays) somehow.
But instead of creating a list of lists out of the numpy arrays, you can create a set of tuples instead and store it:
set_of_arrays_as_tuples = set([tuple(array) for array in lst if array is not None])
Then, any subsequent query to check presence in the set can be done in constant time, instead of linear time:
tuple(arr) in set_of_arrays_as_tuples
->True
My array looks like this:
a = ([1,2],[2,3],[4,5],[3,8])
I did the following to delete odd indexes :
a = [v for i, v in enumerate(a) if i % 2 == 0]
but it dives me now two different arrays instead of one two dimensional:
a= [array([1, 2]), array([4, 5])]
How can I keep the same format as the beginning? thank you!
That is as simple as
a[::2]
which yields the lines with even index.
Use numpy array indexing, not comprehensions:
c = a[list(range(0,len(a),2)),:]
If you define c as the output of a list comprehension, it will return a list of one-dimensional numpy arrays. Instead, using the proper indexing maintains the result a numpy array.
Note than instead of "deleting" the odd indices, what we do is specify what to keep: take all lines with an even index (the list(range(0,len(a),2)) part) and for each line take all elements (the : part)
Suppose I have 2D array, for simplicity, a=np.array([[1,2],[3,4]]). I want to convert it to list of arrays, so that the result would be:
b=[np.array([1,2]), np.array([3,4])]
I found out that there is np.ndarray.tolist() function, but it converts N-D array into nested list. I could have done in a for loop (using append method), but it is not efficient/elegant.
In my real example I am working with 2D arrays of approximately 10000 x 50 elements and I want list that contains 50 one dimensional arrays, each of the shape (10000,).
How about using list:
a=np.array([[1,2],[3,4]])
b = list(a)
Why don't you use list comprehension as follows without using any append:
a=np.array([[1,2],[3,4]])
b = [i for i in a]
print (b)
Output
[array([1, 2]), array([3, 4])]
I have a numpy array arr which is shaped (100,)
arr.shape() #(100,)
here are 100 lists within this array. The lists are strings of characters with no spaces, around length 30
'TBTBBBBBBBBBEBEBEBEBDLKDJFDFIKKKKK'
This array has a "matrix-esque" shape. How can I either (a) tell the lengths of each of the lists in this array or (b) reformat this array so that arr.shape() gives me two dimensions, i.e. arr.shape() gives (100,30)?
Also, it may not be that every list is of the same length (some may be 28, not 30):
How can I check for this behavior? What will numpy.shape() output in such a case?
You can use a list comprehension to determine the length of each string in the array:
arr = np.array(['aasdfads', 'asfdads', 'fdfsdfaf'])
>>> [len(i) for i in arr]
[8, 7, 8]
Or take the max:
>>> max([len(i) for i in arr])
8
I have a numpy array and I want to delete the first 3 elements of the array. I tried this solution:
a = np.arange(0,10)
i=0
while(i<3):
del a[0]
i=i+1
This gives me an error that "ValueError: cannot delete array elements". I do not understand why this is the case. i'd appreciate the help thanks!
Numpy arrays have a fixed size, hence you cannot simply delete an element from them. The simplest way to achieve what you want is to use slicing:
a = a[3:]
This will create a new array starting with the 4th element of the original array.
For certain scenarios, slicing is just not enough. If you want to create a subarray consisting of specific elements from the original array, you can use another array to select the indices:
>>> a = arange(10, 20)
>>> a[[1, 4, 5]]
array([11, 14, 15])
So basically, a[[1,4,5]] will return an array that consists of the elements 1,4 and 5 of the original array.
It works for me:
import numpy as np
a = np.delete(a, k)
where "a" is your numpy arrays and k is the index position you want delete.
Hope it helps.
numpy arrays don't support element deletion. Why don't you just use slicing to achieve what you want?
a = a[3:]
You can convert it into a list and then try regular delete commands like pop, del, eg.
a = np.array([1,2,3,4,5])
l = list(a)
l.pop(3)
l
>>[1, 2, 3, 5]