Reproducible setup
I have an array of n pairs of indices:
indexarray=\
np.array([[0,2,4,6],
[1,3,5,7]])
I also have a 2D array:
zeros = np.zeros((10,9))
and a list of n values:
values = [1,2,3,4]
I would like to add each kth element from the values list to the element in the zeros list having indeces equal to the kth indices pair
A solution
# works, but for loop is not suitable for real-world use-case
for index, (row, col) in enumerate(indexarray.T):
zeros[row, col] = values[index]
Visualize what I get:
plt.imshow(zeros)
Results as expected.
How can I do this without iteration?
Similar but different questions:
Index 2D numpy array by a 2D array of indices without loops : here the output is an array of pairs of indices, not a 2D array, as here.
Fill 2D numpy array from three 1D numpy arrays : setup is more complicated, they create a 2D array from 1D arrays, unlike here, where we already have a 2D array
numpy arrays: filling and extracting data quickly : way more complicated setup, do not start from 2D array
How to convert List of Lists of Tuples- pairs (index,value) into 2D numpy array : aim is different and for loop is not avoided
Simply use:
import numpy as np
indexarray = np.array([[0, 2, 4, 6],
[1, 3, 5, 7]])
values = [1, 2, 3, 4]
rows, cols = indexarray[0], indexarray[1]
zeros = np.zeros((10, 9))
zeros[rows, cols] = values
print(zeros)
Output
[[0. 1. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 2. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 3. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 4. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0.]]
An alternative that will add together repeating coordinates, is to use add.at:
np.add.at(zeros, (rows, cols), values)
A second alternative is to use a sparse matrix constructor, for example:
from scipy.sparse import csr_matrix
rows, cols = indexarray[0], indexarray[1]
zeros = csr_matrix((values, (rows, cols)), shape=(10, 9)).toarray()
Output
[[0 1 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0]
[0 0 0 2 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 3 0 0 0]
[0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 4 0]
[0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0]]
You can directly use indexarray in indexing.
r, c = indexarray
zeros[r, c] = values
You can simply use:
zeros[indexarray[0], indexarray[1]] = values
Related
I am currently trying to iterate over a matrix and modifying the elements inside it following some logic.
I tried using the standard procedure for iterating matrices, but this only outputs the element at the current index, without updating the matrix itself.
This is what i have tried:
for row in initial_matrix:
for element in row:
if np.random.rand() > 0.5: element = 0
print(element)
print(initial_matrix)
This, however, does not update initial matrix, I also tried:
for row in range(len(initial_matrix)):
for element in range(row):
if np.random.rand() > 0.5: initial_matrix[row, element] = 0
print(element)
print(initial_matrix)
This is somehow working, but only in the lower diagonal of the matrix, while the upper remains unchanged.
Here is the output:
0
0
1
0
1
2
0
1
2
3
[[1. 1. 1. 1. 1.]
[0. 1. 1. 1. 1.]
[1. 1. 1. 1. 1.]
[0. 0. 1. 1. 1.]
[0. 1. 1. 0. 1.]]
import numpy as np
initial_matrix = np.ones([10,5])
print(initial_matrix)
for row in initial_matrix:
for element in row:
if np.random.rand() > 0.5:
element = 0
# Nothing will change
print(initial_matrix)
Basically you're not changing the values for the initial matrix with this approach
[[1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1.]]
to better understand this let's take a simple example
initial_list=[1,1,1,1]
for i in initial_list:
i=0
print(initial_list)
this will output the initial list as it is without any modifications because you're modifying the variable i and not the contents of the list itself, if you want to modify the list you can do something like this instead :
initial_list=[1,1,1,1]
for i in range(len(initial_list)):
initial_list[i]=0
print(initial_list)
Now let's apply the same thing to your problem
#Iterate through the rows and columns and change the initial matrix
for i in range(initial_matrix.shape[0]):
for j in range(initial_matrix.shape[1]):
if np.random.rand() > 0.5:
initial_matrix[i,j] = 0
print(initial_matrix)
[[0. 0. 0. 0. 0.]
[0. 1. 1. 1. 0.]
[0. 1. 0. 0. 1.]
[0. 1. 0. 1. 1.]
[1. 0. 1. 0. 1.]
[0. 1. 1. 0. 0.]
[0. 1. 0. 0. 1.]
[1. 0. 0. 1. 0.]
[1. 0. 0. 0. 0.]
[0. 1. 0. 0. 0.]]
Here's a minimalist modification (UPDATED to use np.array throughout) to your code which will do what I believe you are asking:
import numpy as np
initial_matrix = np.array([
[1,1,1,1,1],
[1,1,1,1,1],
[1,1,1,1,1],
[1,1,1,1,1],
[1,1,1,1,1]])
for row in range(len(initial_matrix)):
for element in range(len(initial_matrix[row])):
if np.random.rand() > 0.5:
initial_matrix[row, element] = 0
print(initial_matrix)
Output:
[[0 1 1 1 0]
[1 1 1 0 0]
[0 0 0 0 0]
[0 1 1 0 0]
[1 0 0 1 0]]
Here, I have assumed that you start with a matrix containing 1 in every position and that you want to change this to 0 where your random() criterion is met.
As you can see, an adjustment to the inner loop logic of your original code was helpful in getting this to work.
import numpy as np
a = np.random.rand(3,4)
print(a)
b = np.random.rand(3,4)
print(b)
a[ b > 0.5]=0
print(a)
a = a > 0.5
print(a.astype(int))
You can index into the array with boolean results like this.
Output:
[[0.21577153 0.4810459 0.88036672 0.93817657]
[0.48424368 0.88673521 0.26706288 0.47468637]
[0.02435961 0.75210616 0.18391152 0.80976478]]
[[0.27385928 0.84570069 0.55326907 0.57076882]
[0.11333208 0.26364198 0.26381841 0.57497278]
[0.29163378 0.08612894 0.37857834 0.59921316]]
[[0.21577153 0. 0. 0. ]
[0.48424368 0.88673521 0.26706288 0. ]
[0.02435961 0.75210616 0.18391152 0. ]]
[[0 0 0 0]
[0 1 0 0]
[0 1 0 0]]
If you want to output boolean array in terms of integers you can use astype() function.
I'm trying to learn how to work with Numpy arrays in python and working on a task where the goal is to append certain values from a square function to an np array.
To be specific, trying to append to the array in such a way that the result looks like this.
[[0, 0], [1, 1], [2, 4], [3, 9], [4, 16], [5, 25](....)
In other words kind of like using a for loop to append to a nested list kind of like this:
N = 101
def f(x):
return x**2
list1 = []
for i in range(N+1):
list1.append([i])
list1[i].append(f(i))
print(list1)
When I try to do this similarly whit Numpy arrays like below:
import numpy as np
N = 101
x_min = 1
x_max = 10
y = np.zeros(N)
x = np.linspace(x_min,x_max, N)
def f(x):
return x**2
for i in y:
np.append(y,f(x))
print(y)
I get the following output:
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0.]
... which is obviously wrong
Arrays as a datatype are quite new to me, so I would massively appreciate it if anyone could help me out.
Best regards from a rookie who is motivated to learn and welcome all help.
It is kind of un-numpy-thonic (if that's a thing) to mix and match numpy arrays with vanilla python operations like for loops and appending. If I were to do this in pure numpy I would first start with your original array
>>> import numpy as np
>>> N = 101
>>> values = np.arange(N)
>>> values
array([ 0, 1, 2, ..., 99, 100])
then I would generate your squared array to create your 2D result
>>> values = np.array([values, values**2])
>>> values.T
array([[ 0, 0],
[ 1, 1],
[ 2, 4],
...
[ 98, 9604],
[ 99, 9801],
[ 100, 10000]])
Numpy gets its speed advantages in two primary ways:
Faster execution of large numbers of repeated operations (i.e. without Python for loops)
Avoiding moving data in memory (i.e. re-allocating memory space).
It's impossible to implement an indefinite append operation with Numpy arrays and still get both of these advantages. So don't do it!
I can't see in your example why an append is necessary because you know the size of the result array in advance (N).
Perhaps what you are looking for instead is vectorized function execution and assignment:
y[:] = f(x)
print(y)
(Instead of your for loop.)
This produces:
[ 1. 1.1881 1.3924 1.6129 1.8496 2.1025 2.3716 2.6569
2.9584 3.2761 3.61 3.9601 4.3264 4.7089 5.1076 5.5225
5.9536 6.4009 6.8644 7.3441 7.84 8.3521 8.8804 9.4249
9.9856 10.5625 11.1556 11.7649 12.3904 13.0321 13.69 14.3641
...etc.
Or, to get a similar output to your first bit of code:
y = np.zeros((N, 2))
y[:, 0] = x
y[:, 1] = f(x)
You could simply broadcast the operation and column_stack them.
col1 = np.arange(N)
col2 = col1 **2
list1 = np.column_stack((col1,col2))
I'm trying to import data from csv file and I get two different types of arrays when I use pandas' read function and numpy's getfromtxt resulting in two different arrays:
[[ 1. 0. 1. ..., 1. 0. 0.]
[ 0. 1. 1. ..., 1. 0. 0.]
[ 0. 1. 1. ..., 1. 0. 0.]
...,
[ 0. 1. 1. ..., 1. 0. 0.]
[ 1. 0. 1. ..., 1. 0. 0.]
[ 1. 0. 1. ..., 1. 0. 0.]]
When I use the following line of code:
from numpy import genfromtxt
df = genfromtxt('C:/Users/m15x/Desktop/UFABC/PDPD/inputX(editado_bits).csv', delimiter=',')
X = df
print(X)
And:
[[1 0 1 ..., 1 0 0]
[0 1 1 ..., 1 0 0]
[0 1 1 ..., 1 0 0]
...,
[1 0 1 ..., 1 0 0]
[1 0 1 ..., 0 0 1]
[1 0 1 ..., 1 0 0]]
When I use the this line of code:
import pandas as pd
df = pd.read_csv('C:/Users/m15x/Desktop/UFABC/PDPD/input(editado_bits).csv')
X1 = df.loc[0:86,'Initiation (Gradual)' : 'Otoscopy (cerumen)']
X = X1.values
print(X)
What is the difference between them?
Try in Python shell:
>>> type(1.)
<class 'float'>
>>> type(1)
<class 'int'>
I have a numpy array of shape [12, 8, 5, 5]. I want to modify the values of 3rd and 4th dimension for each element.
For e.g.
import numpy as np
x = np.zeros((12, 80, 5, 5))
print(x[0,0,:,:])
Output:
[[ 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0.]]
Modify values:
y = np.ones((5,5))
x[0,0,:,:] = y
print(x[0,0,:,:])
Output:
[[ 1. 1. 1. 1. 1.]
[ 1. 1. 1. 1. 1.]
[ 1. 1. 1. 1. 1.]
[ 1. 1. 1. 1. 1.]
[ 1. 1. 1. 1. 1.]]
I can modify for all x[i,j,:,:] using two for loops. But, I was wondering if there is any pythonic way to do it without running two loops. Just curious to know :)
UPDATE
Actual use case:
dict_weights = copy.deepcopy(combined_weights)
for i in range(0, len(combined_weights[each_layer][:, 0, 0, 0])):
for j in range(0, len(combined_weights[each_layer][0, :, 0, 0])):
# Extract 5x5
trans_weight = combined_weights[each_layer][i,j]
trans_weight = np.fliplr(np.flipud(trans_weight ))
# Update
dict_weights[each_layer][i, j] = trans_weight
NOTE: The dimensions i, j of combined_weights can vary. There are around 200 elements in this list with varied i and j dimensions, but 3rd and 4th dimensions are always same (i.e. 5x5).
I just want to know if I can updated the elements combined_weights[:,:,5, 5] with transposed values without running 2 for loops.
Thanks.
Simply do -
dict_weights[each_layer] = combined_weights[each_layer][...,::-1,::-1]
I have a numpy array D of dimensions 4x4
I want a new numpy array based on an user defined value v
If v=2, the new numpy array should be [D D].
If v=3, the new numpy array should be [D D D]
How do i initialise such a numpy array as numpy.zeros(v) dont allow me to place arrays as elements?
If I understand correctly, you want to take a 2D array and tile it v times in the first dimension? You can use np.repeat:
# a 2D array
D = np.arange(4).reshape(2, 2)
print D
# [[0 1]
# [2 3]]
# tile it 3 times in the first dimension
x = np.repeat(D[None, :], 3, axis=0)
print x.shape
# (3, 2, 2)
print x
# [[[0 1]
# [2 3]]
# [[0 1]
# [2 3]]
# [[0 1]
# [2 3]]]
If you wanted the output to be kept two-dimensional, i.e. (6, 2), you could omit the [None, :] indexing (see this page for more info on numpy's broadcasting rules).
print np.repeat(D, 3, axis=0)
# [[0 1]
# [0 1]
# [0 1]
# [2 3]
# [2 3]
# [2 3]]
Another alternative is np.tile, which behaves slightly differently in that it will always tile over the last dimension:
print np.tile(D, 3)
# [[0, 1, 0, 1, 0, 1],
# [2, 3, 2, 3, 2, 3]])
You can do that as follows:
import numpy as np
v = 3
x = np.array([np.zeros((4,4)) for _ in range(v)])
>>> print x
[[[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]]
[[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]]
[[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]]]
Here you go, see if this works for you.
import numpy as np
v = raw_input('Enter: ')
To intialize the numpy array of arrays from user input (obviously can be whatever shape you're wanting here):
b = np.zeros(shape=(int(v),int(v)))
I know this isn't initializing a numpy array but since you mentioned wanting an array of [D D] if v was 2 for example, just thought I'd throw this in as another option as well.
new_array = []
for x in range(0, int(v)):
new_array.append(D)