I am new to programming and python. I am trying to create a matrix(6, 6) with random numbers within a certain range. Each number must be twice. Should I use matrix, multi dimensional array or list of lists? I'd like to know what is the easiest way to achieve this.
This is what I have right now:
rows = 6
columns = 6
range(0, 18)
matrix = [[0 for x in range(rows)] for y in range(columns)]
# Loop into matrix to fill with random numbers withing the range property.
# Matrix should have the same number twice.
for row in matrix:
print(row)
You could:
Generate a list of 36 numbers having each value of 0-17 twice as 2 * list(range(18))
Shuffle the list of numbers
Slice the list to equal chunks of 6
The result will be a matrix that meets your requirements, using only the standard library.
Something like this:
import random
nums = 2 * list(range(18))
random.shuffle(nums)
matrix = [nums[i:i+6] for i in range(0, 36, 6)]
Assuming you're looking for integers, it's as easy as this:
import numpy as np
import random
number_sample = list(range(18))*2 #Get two times numbers from 0 to 17
random.shuffle(number_sample) #Shuffle said numbers
np.array(number_sample).reshape(6,6) #Reshape into matrix
Output:
array([[ 1, 0, 5, 1, 8, 15],
[ 9, 3, 15, 17, 0, 14],
[ 7, 9, 11, 7, 16, 13],
[ 4, 10, 8, 12, 5, 6],
[ 6, 11, 4, 14, 3, 13],
[10, 16, 2, 17, 2, 12]])
Edit: Changed answer to reflect changes in your question
Related
How can I write code that adds up all the numbers in between the indices? The arrays numbers and indices are correlated. The first two index values are 0-3 so the numbers between indices 0-3 are being added up 1 + 5 + 6 = 12. The expected value is what I am trying to find. I am trying to get the results without using a for loop.
numbers = np.array([1, 5, 6, 7, 4, 3, 6, 7, 11, 3, 4, 6, 2, 20]
indices = np.array([0, 3 , 7, 11])
Expected output:
[12, 41, 22]
I'm not sure how you got the expected output - from my calculation, the sum between the indices should be [12, 20, 25]. The following code calculates this:
numbers = np.array([1, 5, 6, 7, 4, 3, 6, 7, 11, 3, 4, 6, 2, 20])
indexes = np.array([0, 3, 7, 11])
tmp = np.zeros(len(numbers) + 1)
np.cumsum(numbers, out=tmp[1:])
result = np.diff(tmp[indexes])
The output of this is [12, 20, 25]
How does this work? It creates an array that is just one size larger than the numbers array (in order to have the first element be zero). Then it calculates the cumulative sum of the elements, starting at index 1 of the tmp array. Then, it takes the diff of the tmp array at the indices provided. As an example, it takes the different of the cumulative sum of the array from index 3 (value = 12) to index 7 (value = 32), 32-12 = 20.
You are likely looking for np.add.reduceat:
>>> np.add.reduceat(numbers, indices)
array([12, 20, 25, 28], dtype=int32)
How do you index a numpy array that wraps around when its out of bounds?
For example, I have 3x3 array:
import numpy as np
matrix = np.array([[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15]])
##
[[ 1 2 3 4 5]
[ 6 7 8 9 10]
[11 12 13 14 15]]
Say I would like to index the values around index (2,4) where value 15 is located. I would like to get back the array with values:
[[9, 10, 6]
[14, 15, 11]
[4, 5, 1]]
Basically all the values around 15 was returned, assuming it wraps around
A fairly standard idiom to find the neighboring elements in a numpy array is arr[x-1:x+2, y-1:y+2]. However, since you want to wrap, you can pad your array using wrap mode, and offset your x and y coordinates to account for this padding.
This answer assumes that you want the neighbors of the first occurence of your desired element.
First, find the indices of your element, and offset to account for padding:
x, y = np.unravel_index((m==15).argmax(), m.shape)
x += 1; y += 1
Now pad, and index your array to get your neighbors:
t = np.pad(m, 1, mode='wrap')
out = t[x-1:x+2, y-1:y+2]
array([[ 9, 10, 6],
[14, 15, 11],
[ 4, 5, 1]])
Here's how you can do it without padding. This can generalize easily to when you want more than just one neighbor and without the overhead of padding the array.
def get_wrapped(matrix, i, j):
m, n = matrix.shape
rows = [(i-1) % m, i, (i+1) % m]
cols = [(j-1) % n, j, (j+1) % n]
return matrix[rows][:, cols]
res = get_wrapped(matrix, 2, 4)
Let me explain what's happening here return matrix[rows][:, cols]. This is really two operations.
The first is matrix[rows] which is short hand for matrix[rows, :] which means give me the selected rows, and all columns for those rows.
Then next we do [:, cols] which means give me all the rows and the selected cols.
The take function works in-place.
>>> a = np.arange(1, 16).reshape(3,5)
array([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]])
>>> b = np.take(a, [3,4,5], axis=1, mode='wrap')
array([[ 4, 5, 1],
[ 9, 10, 6],
[14, 15, 11]])
>>> np.take(b, [1,2,3], mode='wrap', axis=0)
array([[ 9, 10, 6],
[14, 15, 11],
[ 4, 5, 1]])
Imagine I have something like this:
import numpy as np
arra = np.arange(16).reshape(2, 2, 4)
which gives
array([[[0, 1, 2, 3],
[4, 5, 6, 7]],
[[8, 9, 10, 11],
[12, 13, 14, 15]]])
and I want to make a loop that runs along specific subarrays (in this case, I want to run along each 'column' of each 'matrix') and sum the result (that is, selecting 0 and 4 and summing them (4), selecting 1 and 5 and summing them (6), ..., selecting 3 and 7 and summing them (10), selecting 8 and 12 and summing them (20), ..., selecting 11 and 15 and summing them (26)).
I had thought doing that with the apparently natural:
for i in arra[i, j, k]:
for j in arra[i, j, k]:
for k in arra[i, j, k]:
sum...
The problem is that Python certainly doesn't allow to do what I want in this way. If it were a 2D array it would be easier as I know that the iterator first runs through the rows, so you can transpose to run along the columns, but for a multidimensional (3D in this case) array (N, M, P) with N, M, P >> 1, I was wondering how it could be done.
EDIT: This question has a continuation here: Choosing and iterating specific sub-arrays in multidimensional arrays in Python
You can use map to get this done:
import numpy as np
arra = np.arange(16).reshape(2, 2, 4)
Then the command:
map(sum, arra)
gives you the desired output:
[array([ 4, 6, 8, 10]), array([20, 22, 24, 26])]
Alternatively, you can also use a list comprehension:
res = [sum(ai) for ai in arra]
Then res looks like this:
[array([ 4, 6, 8, 10]), array([20, 22, 24, 26])]
EDIT:
If you want to add identical rows - as you mentioned in the comments below this answer - you can do (using zip):
map(sum, zip(*arra))
which gives you the desired output:
[array([ 8, 10, 12, 14]), array([16, 18, 20, 22])]
For the sake of completeness also the list comprehension:
[sum(ai) for ai in zip(*arra)]
which gives you the same output.
This is a question that comes from the post here Iterating and selecting a specific array from a multidimensional array in Python
In that post, user #Cleb solved what it was my original problem: how to perform a sum through columns in a 3d array:
import numpy as np
arra = np.arange(16).reshape(2, 2, 4)
which gives
array([[[0, 1, 2, 3],
[4, 5, 6, 7]],
[[8, 9, 10, 11],
[12, 13, 14, 15]]])
and the problem was how to perform the sum of columns in each matrix, i. e., 0 + 4, 1 + 5, ... , 8 + 12, ..., 11 + 15. It was solved by #Cleb.
Then I wondered how to do it in the case of a sum of 0 + 8, 1 + 9, ..., 4 + 12, ..., 7 + 15, (odd and even columns) which was also solved by #Cleb.
But then I wondered if there are a general idea (which can be modified in each specific case). Imagine you can add the first and the last rows and the center rows, in columns, separately, i. e., 0 + 12, 1 + 13, ..., 3 + 15, 4 + 8, 5 + 9, ..., 7 + 11.
Is there a general way? Thank you.
Depending on the how exactly arra is defined, you can shift your values appropriately using np.roll:
arra_mod = np.roll(arra, arra.shape[2])
arra_mod then looks as follows:
array([[[12, 13, 14, 15],
[ 0, 1, 2, 3]],
[[ 4, 5, 6, 7],
[ 8, 9, 10, 11]]])
Now you can simply use the command from your previous question to get your desired output:
map(sum, arra_mod)
which gives you the desired output:
[array([12, 14, 16, 18]), array([12, 14, 16, 18])]
You can also use a list comprehension
[sum(ai) for ai in arra_mod]
which gives you the same output.
If you prefer one-liner, you can therefore simply do:
map(sum, np.roll(arra, arra.shape[2]))
Is there a way to change the order of the columns in a numpy 2D array to a new and arbitrary order?
For example, I have an array
array([[10, 20, 30, 40, 50],
[ 6, 7, 8, 9, 10]])
and I want to change it into, say
array([[10, 30, 50, 40, 20],
[ 6, 8, 10, 9, 7]])
by applying the permutation
0 -> 0
1 -> 4
2 -> 1
3 -> 3
4 -> 2
on the columns. In the new matrix, I therefore want the first column of the original to stay in place, the second to move to the last column and so on.
Is there a numpy function to do it? I have a fairly large matrix and expect to get even larger ones, so I need a solution that does this quickly and in place if possible (permutation matrices are a no-go)
Thank you.
This is possible in O(n) time and O(n) space using fancy indexing:
>>> import numpy as np
>>> a = np.array([[10, 20, 30, 40, 50],
... [ 6, 7, 8, 9, 10]])
>>> permutation = [0, 4, 1, 3, 2]
>>> idx = np.empty_like(permutation)
>>> idx[permutation] = np.arange(len(permutation))
>>> a[:, idx] # return a rearranged copy
array([[10, 30, 50, 40, 20],
[ 6, 8, 10, 9, 7]])
>>> a[:] = a[:, idx] # in-place modification of a
Note that a[:, idx] is returning a copy, not a view. An O(1)-space solution is not possible in the general case, due to how numpy arrays are strided in memory.
The easiest way in my opinion is:
a = np.array([[10, 20, 30, 40, 50],
[6, 7, 8, 9, 10]])
print(a[:, [0, 2, 4, 3, 1]])
the result is:
[[10 30 50 40 20]
[6 8 10 9 7 ]]
I have a matrix based solution for this, by post-multiplying a permutation matrix to the original one. This changes the position of the elements in original matrix
import numpy as np
a = np.array([[10, 20, 30, 40, 50],
[ 6, 7, 8, 9, 10]])
# Create the permutation matrix by placing 1 at each row with the column to replace with
your_permutation = [0,4,1,3,2]
perm_mat = np.zeros((len(your_permutation), len(your_permutation)))
for idx, i in enumerate(your_permutation):
perm_mat[idx, i] = 1
print np.dot(a, perm_mat)
If you're looking for any random permuation, you can do it in one line if you transpose columns into rows, permute the rows, then transpose back:
a = np.random.permutation(a.T).T