I'm looking for creating a random dimension numpy array, iterate and replace values per 10 for example.
I tried :
# Import numpy library
import numpy as np
def Iter_Replace(x):
print(x)
for i in range(x):
x[i] = 10
print(x)
def main():
x = np.array(([1,2,2], [1,4,3]))
Iter_Replace(x)
main()
But I'm getting this error :
TypeError: only integer scalar arrays can be converted to a scalar index
There is a numpy function for this, numpy.full or numpy.full_like:
>>> x = np.array(([1,2,2], [1,4,3]))
>>> np.full(x.shape, 10)
array([[10, 10, 10],
[10, 10, 10]])
# OR,
>>> np.full_like(x, 10)
array([[10, 10, 10],
[10, 10, 10]])
If you want to iterate you can either use itertools.product:
>>> from itertools import product
>>> def Iter_Replace(x):
indices = product(*map(range, x.shape))
for index in indices:
x[tuple(index)] = 10
return x
>>> x = np.array([[1,2,2], [1,4,3]])
>>> Iter_Replace(x)
array([[10, 10, 10],
[10, 10, 10]])
Or, use np.nditer
>>> x = np.array([[1,2,2], [1,4,3]])
>>> for index in np.ndindex(x.shape):
x[index] = 10
>>> x
array([[10, 10, 10],
[10, 10, 10]])
You have two errors. There are missing parenthesis in the first line of main:
x = np.array(([1,2,2], [1,4,3]))
And you must replace range(x) by range(len(x)) in the Iter_Replace function.
Related
In python numpy, how to replace some rows in array A with array B if we know the index.
For example
we have
a = np.array([[1,2],[3,4],[5,6]])
b = np.array([[10,10],[1000, 1000]])
index = [0,2]
I want to change a to
a = np.array([[10,10],[3,4],[1000,1000]])
I have considered the funtion np.where but it need to create the bool condition, not very convenient,
I would do it following way
import numpy as np
a = np.array([[1,2],[3,4],[5,6]])
b = np.array([[10,10],[1000, 1000]])
index = [0,2]
a[index] = b
print(a)
gives output
[[ 10 10]
[ 3 4]
[1000 1000]]
You can use :
a[index] = b
For example :
import numpy as np
a = np.array([[1,2],[3,4],[5,6]])
b = np.array([[10,10],[1000, 1000]])
index = [0,2]
a[index] = b
print(a)
Result :
[[ 10 10]
[ 3 4]
[1000 1000]]
In Python's NumPy library, you can use the numpy.put() method to replace some rows in array A with array B if you know the index. Here's an example:
import numpy as np
# Initialize array A
A = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# Initialize array B
B = np.array([[10, 20, 30], [40, 50, 60]])
# Indices of the rows to be replaced in array A
indices = [0, 1]
# Replace rows in array A with rows in array B
np.put(A, indices, B)
print(A)
In this example, the first two rows in array A are replaced with the first two rows in array B, so the output will be
[[10 20 30]
[40 50 60]
[ 7 8 9]]
Simply a[indices] = b or if you want to be more fancy np.put(a, indices, b)
Can this for loop be written in a simpler way?
import itertools
import numpy as np
def f(a, b, c): # placeholder for a complex function
print(a+b+c)
a = np.arange(12).reshape(3, 4)
for y, x in itertools.product(range(a.shape[0]-1), range(a.shape[1]-1)):
f(a[y, x], a[y, x+1], a[y+1, x])
The other options I tried, look more convoluted, e.g.:
it = np.nditer(a[:-1, :-1], flags=['multi_index'])
for e in it:
y, x = it.multi_index
f(a[y, x], a[y, x+1], a[y+1, x])
Posting it as an answer, and sorry if this is too obvious, but isn't this simply
for y in range(a.shape[0]-1):
for x in range(a.shape[1]-1):
f(a[y, x], a[y, x+1], a[y+1, x])
If I use your method I got:
expected = [5, 8, 11, 17, 20, 23]
but you can vectorize the computation by generating an array containing the data in a more suitable way:
a_stacked = np.stack([a[:-1, :-1], a[:-1, 1:], a[1:, :-1]], axis=0)
From there multiple solutions:
If you already know the function will be the sum:
>>> a_stacked.sum(axis=0)
array([[ 5, 8, 11],
[17, 20, 23]])
If you know that your function is already vectorized:
>>> f(*a_stacked)
array([[ 5, 8, 11],
[17, 20, 23]])
If your function does not vectorize, you can use np.vectorize for convenience (no performance improvement):
>>> np.vectorize(f)(*a_stacked)
array([[ 5, 8, 11],
[17, 20, 23]])
Obviously you can flatten the array next.
I would like to know if I have generated the 3 arrays in the manner below, how can I sum all the numbers up from all 3 arrys without summing up the ones that appear in each array.
(I would like to only som upt 10 once but I cant add array X_1 andX_2 because they both have 10 and 20, I only want to som up those numbers once.)
Maybe this can be done by creating a new array out of the X_1, X_2 and X_3 what leave out doubles?
def get_divisible_by_n(arr, n):
return arr[arr%n == 0]
x = np.arange(1,21)
X_1=get_divisible_by_n(x, 2)
#we get array([ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20])
X_2=get_divisible_by_n(x, 5)
#we get array([ 5, 10, 15, 20])
X_3=get_divisible_by_n(x, 3)
#we get array([3, 6, 9, 12, 15, 18])
it is me again!
here is my solution using numpy, cuz i had more time this time:
import numpy as np
arr = np.arange(1,21)
divisable_by = lambda x: arr[np.where(arr % x == 0)]
n_2 = divisable_by(2)
n_3 = divisable_by(3)
n_5 = divisable_by(5)
what_u_want = np.unique( np.concatenate((n_2, n_3, n_5)) )
# [ 2, 3, 4, 5, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20]
Not really efficient and not using numpy but here is one solution:
def get_divisible_by_n(arr, n):
return [i for i in arr if i % n == 0]
x = [i for i in range(21)]
X_1 = get_divisible_by_n(x, 2)
X_2 = get_divisible_by_n(x, 5)
X_3 = get_divisible_by_n(x, 3)
X_all = X_1+X_2+X_3
y = set(X_all)
print(sum(y)) # 142
I have a 3D matrix ‘DATA’ whose dimension is 100(L)X200(B)X50(H). The values are random for each grid point.
I want to the find the number of points where the values are between 10 and 20 in each vertical column. The output will be a 2D matrix.
For this I used the following code:
out = []
for i in range(np.shape(DATA)[0]):
for j in range(np.shape(DATA)[1]):
a = DATA[i,j,:]
b = a[(a>25) & (a<30)]
c = len(b)
out.append(c)
but I am not getting the 2D matrix. Instead I am getting an array
Please Help
if you want to leverage numpy functionality:
import numpy as np
data = np.random.randint(0, 50, size=(100,200,50))
range_sum = np.sum(np.logical_and(np.less_equal(data, 20),
np.greater_equal(data, 10)
), axis=-1)
range_sum.shape
Out[6]: (100, 200)
range_sum
Out[7]:
array([[11, 12, 12, ..., 13, 9, 10],
[ 6, 12, 11, ..., 10, 14, 5],
[11, 11, 16, ..., 10, 12, 15],
...,
[11, 17, 9, ..., 12, 12, 11],
[ 9, 8, 10, ..., 7, 15, 12],
[12, 10, 11, ..., 12, 11, 19]])
You're using out as a list, and appending each value. Here's a quick modification to your code that should give you the desired result:
out = []
for i in range(np.shape(DATA)[0]):
out.append([]) # make a second dim for each i
for j in range(np.shape(DATA)[1]):
a = DATA[i,j,:]
b = a[(a>25) & (a<30)]
c = len(b)
out[i].append(c)
The change is that I made out a list of lists. In each iteration over i, we append a new list. Then in the inner loop, we append values to the list at index i.
Update
If you want an numpy.ndarray instead, you can modify your code as follows:
import numpy as np
out = np.ndarray(np.shape(DATA)) # initialize to the desired shape
for i in range(np.shape(DATA)[0]):
for j in range(np.shape(DATA)[1]):
a = DATA[i,j,:]
b = a[(a>25) & (a<30)]
c = len(b)
out[i][j] = c
In Matlab I can do this:
s1 = 'abcdef'
s2 = 'uvwxyz'
s1(1:2:end) = s2(1:2:end)
s1 is now 'ubwdyf'
This is just an example of the general:
A(I) = B
Where A,B are vectors, I a vector of indices and B is the same length as I. (Im ignoring matrices for the moment).
What would be the pythonic equivalent of the general case in Python? Preferably it should also run on jython/ironpython (no numpy)
Edit: I used strings as a simple example but solutions with lists (as already posted, wow) are what I was looking for. Thanks.
>>> s1 = list('abcdef')
>>> s2 = list('uvwxyz')
>>> s1[0::2] = s2[0::2]
>>> s1
['u', 'b', 'w', 'd', 'y', 'f']
>>> ''.join(s1)
'ubwdyf'
The main differences are:
Strings are immutable in Python. You can use lists of characters instead though.
Indexing is 0-based in Python.
The slicing syntax is [start : stop : step] where all parameters are optional.
Strings are immutable in Python, so I will use lists in my examples.
You can assign to slices like this:
a = range(5)
b = range(5, 7)
a[1::2] = b
print a
which will print
[0, 5, 2, 6, 4]
This will only work for slices with a constant increment. For the more general A[I] = B, you need to use a for loop:
for i, b in itertools.izip(I, B):
A[i] = b
NumPy arrays can be indexed with an arbitrary list, much as in Matlab:
>>> x = numpy.array(range(10)) * 2 + 5
>>> x
array([ 5, 7, 9, 11, 13, 15, 17, 19, 21, 23])
>>> x[[1,6,4]]
array([ 7, 17, 13])
and assignment:
>>> x[[1,6,4]] = [0, 0, 0]
>>> x
array([ 5, 0, 9, 11, 0, 15, 0, 19, 21, 23])
Unfortunately, I don't think it is possible to get this without numpy, so you'd just need to loop for those.