Python - how to resize an array and duplicate the elements - python

I've got an array with data like this
a = [[1,2,3],[4,5,6],[7,8,9]]
and I want to change it to
b = [[1,1,2,2,3,3],[1,1,2,2,3,3],[4,4,5,5,6,6],[4,4,5,5,6,6],[7,7,8,8,9,9],[7,7,8,8,9,9]]
I've tried to use numpy.resize() function but after resizing, it gives [[1,2,3,4],[1,2,3,4],[1,2,3,4],[1,2,3,4]]. I can use a for loop to put the numbers at the indexes I need but just wondering if there is any easier way of doing that?
To visualise the task, here is the original array
This is what I want

My initial though was that np.tile would work but in fact what you are looking for is np.repeat twice on two different axes.
Try this runnable example!
#!/usr/bin/env python
import numpy as np
a = [[1,2,3],[4,5,6],[7,8,9]]
b = np.repeat(np.repeat(a, 2, axis=1), 2, axis=0)
b
<script src="https://modularizer.github.io/pyprez/pyprez.min.js"></script>

You can think of your problem as resizing each 1x1 block to a 2x2 block. This can simply be done using numpy.kron(a, b), which operates on each element of a – each 1x1 block – and "expands" it according to b – which should thus be a 2x2 block.
>>> import numpy as np
>>> a = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> np.kron(a, [[1, 1], [1, 1]])
array([[1, 1, 2, 2, 3, 3],
[1, 1, 2, 2, 3, 3],
[4, 4, 5, 5, 6, 6],
[4, 4, 5, 5, 6, 6],
[7, 7, 8, 8, 9, 9],
[7, 7, 8, 8, 9, 9]])
An efficient way to create the second operand for larger structures is using np.ones and related functions.
>>> np.kron(a, np.ones((2,4), dtype=int))
array([[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],
[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],
[4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6],
[4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6],
[7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9],
[7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9]])

Related

Is there a better method to create such a numpy array?

I want a numpy array like this:
b = np.array([[1, 1, 1, 1, 1, 1],
[2, 2, 2, 2, 2, 2],
[3, 3, 3, 3, 3, 3],
[4, 4, 4, 4, 4, 4],
[5, 5, 5, 5, 5, 5],
[6, 6, 6, 6, 6, 6],
[7, 7, 7, 7, 7, 7],
[8, 8, 8, 8, 8, 8],
[9, 9, 9, 9, 9, 9]])
Is there a faster way to create a NumPy array like this instead of typing them manually?
You can do something like this:
>>> np.repeat(np.arange(1, 10).reshape(-1,1), 6, axis=1)
array([[1, 1, 1, 1, 1, 1],
[2, 2, 2, 2, 2, 2],
[3, 3, 3, 3, 3, 3],
[4, 4, 4, 4, 4, 4],
[5, 5, 5, 5, 5, 5],
[6, 6, 6, 6, 6, 6],
[7, 7, 7, 7, 7, 7],
[8, 8, 8, 8, 8, 8],
[9, 9, 9, 9, 9, 9]])
Explanation:
np.arange(1, 10).reshape(-1,1) creates an array
array([[1],
[2],
[3],
[4],
[5],
[6],
[7],
[8],
[9]])
np.repeat(_, 6, axis=1) repeats this 6 times on the first (or second in human words) axis.
Yes. There are plenty of methods. This is one:
np.repeat(np.arange(1,10),6,axis=0).reshape(9,6)
Another method is to use broadcasting:
>>> np.arange(1,10)[:,None] * np.ones(6, dtype=int)
array([[1, 1, 1, 1, 1, 1],
[2, 2, 2, 2, 2, 2],
[3, 3, 3, 3, 3, 3],
[4, 4, 4, 4, 4, 4],
[5, 5, 5, 5, 5, 5],
[6, 6, 6, 6, 6, 6],
[7, 7, 7, 7, 7, 7],
[8, 8, 8, 8, 8, 8],
[9, 9, 9, 9, 9, 9]])
For any w*l size, convert a list of lists into an np.array like so:
w = 6
l = 9
[np.array([[1+i]*w for i in range(d)])
array([[1, 1, 1, 1, 1, 1],
[2, 2, 2, 2, 2, 2],
[3, 3, 3, 3, 3, 3],
[4, 4, 4, 4, 4, 4],
[5, 5, 5, 5, 5, 5],
[6, 6, 6, 6, 6, 6],
[7, 7, 7, 7, 7, 7],
[8, 8, 8, 8, 8, 8],
[9, 9, 9, 9, 9, 9]])
np.transpose(np.array(([np.arange(1,10)] * 6)))
np.arange(1,10) creates an numpy array from 1 to 9.
[] puts the array into a list.
*6 augments the array 6 times.
np.array() converts the resulting structure (list of arrays) to a numpy array
np.transpose() rotates the orientation of the numpy array to get vertical one.

How to swap items in a list within a list python

I am trying to randomly swap 2 items in each list within a list, where those to be swapped are not in another list.
Here is my code
import random
def swap(mylist):
remain = [[1, 2], [4], [], [8, 2], [1, 4], [5, 2, 1], [], [9, 5], [7]]
for x in range(0, 9):
remaining = set(mylist[x]) - set(remain[x])
to_swap = random.sample(remaining, 2)
mylist[x][mylist[x].index(to_swap[0])], mylist[x][mylist[x].index(to_swap[1])] = mylist[x][mylist[x].index(to_swap[1])], mylist[x][mylist[x].index(to_swap[0])]
return mylist
print(swap([[8, 5, 4, 1, 3, 9, 7, 6, 2], [9, 3, 5, 6, 4, 7, 1, 2, 8], [7, 3, 2, 5, 4, 1, 9, 6, 8], [2, 1, 3, 8, 6, 9, 5, 7, 4], [1, 2, 3, 5, 7, 4, 9, 8, 6], [6, 9, 3, 1, 7, 4, 2, 8, 5], [1, 2, 7, 4, 3, 8, 5, 9, 6], [3, 7, 8, 4, 1, 5, 9, 6, 2], [4, 2, 6, 5, 7, 1, 9, 3, 8]]))
Whenever I run this and print out the result, it just prints out my input again.
Does anyone know what is wrong with my code?
Thanks.
Your code performs the swaps with about one half of the sublists. I wonder what the reason of this behavior is *(see below).
If you rewrite the swapping part like this:
i = mylist[x].index(to_swap[0])
j = mylist[x].index(to_swap[1])
mylist[x][i], mylist[x][j] = mylist[x][j], mylist[x][i]
then it works.
UPDATE:
There is no need to access the lists on the right-hand side of the assignment, since we already know the values, so the updated answer would be:
i = mylist[x].index(to_swap[0])
j = mylist[x].index(to_swap[1])
mylist[x][i], mylist[x][j] = to_swap[1], to_swap[0]
*UPDATE 2:
The above mentioned behavior is caused by the fact that in multiple assignments, expressions on the left-hand side are evaluated one by one from left to right. That means the OP's code didn't work in cases where index(to_swap[0]) < index(to_swap[1]).
Example: values 5 and 6 in the first sublist [8, 5, 4, 1, 3, 9, 7, 6, 2]. First, the program will do
mylist[x][mylist[x].index(5)] = 6
modifying the list to [8, 6, 4, 1, 3, 9, 7, 6, 2]. Second, the program will do
mylist[x][mylist[x].index(6)] = 5
modifying it back to [8, 5, 4, 1, 3, 9, 7, 6, 2].

Fastest numpy way to remove a list of cells from a 2d array

I have a very large 2D numpy array of m x n elements. For each row, I need to remove exactly one element. So for example from a 4x6 matrix I might need to delete [0, 1], [1, 4], [2, 3], and [3, 3] - I have this set of coordinates stored in a list. In the end, the matrix will ultimately shrink in width by 1.
Is there a standard way to do this using a mask? Ideally, I need this to be as performant as possible.
Here is a method that use ravel_multi_index() to calculate one-dim index, and then delete() the elements, and reshape back to two-dim array:
import numpy as np
n = 12
a = np.repeat(np.arange(10)[None, :], n, axis=0)
index = np.random.randint(0, 10, n)
ravel_index = np.ravel_multi_index((np.arange(n), index), a.shape)
np.delete(a, ravel_index).reshape(n, -1)
the index:
array([4, 6, 9, 0, 3, 5, 3, 8, 9, 8, 4, 4])
the result:
array([[0, 1, 2, 3, 4, 5, 6, 7, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[0, 1, 2, 3, 4, 5, 6, 8, 9],
[0, 1, 2, 3, 4, 5, 6, 7, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[0, 1, 2, 3, 4, 5, 6, 7, 9],
[0, 1, 3, 4, 5, 6, 7, 8, 9],
[0, 1, 2, 3, 5, 6, 7, 8, 9],
[0, 1, 2, 3, 4, 5, 6, 7, 9],
[0, 1, 2, 3, 4, 5, 6, 7, 9],
[0, 1, 2, 3, 4, 5, 6, 7, 8],
[0, 1, 2, 4, 5, 6, 7, 8, 9]])

simple way to select numpy subarray using boolean conditional vector in python 3

How can you select only the columns of a 2-d numpy array that correspond to a conditional boolean vector?
Say you have a 10x10 matrix, generated by, say:
a = np.random.randint(0,1,(10,10))
a =
array([[4, 9, 1, 9, 5, 2, 1, 7, 6, 5],
[5, 4, 2, 4, 8, 1, 5, 5, 7, 5],
[3, 8, 7, 4, 3, 4, 8, 8, 8, 3],
[5, 4, 4, 4, 9, 6, 7, 1, 6, 8],
[8, 3, 2, 1, 7, 5, 8, 8, 4, 9],
[9, 5, 6, 8, 6, 8, 1, 4, 4, 5],
[5, 4, 3, 2, 8, 3, 2, 2, 8, 6],
[2, 5, 4, 5, 9, 7, 9, 2, 5, 6],
[4, 5, 9, 7, 3, 1, 5, 7, 4, 8],
[6, 1, 3, 8, 8, 3, 2, 6, 6, 7]])
and you want to cut out all the rows corresponding to a vector containing (True/False or 0/1), like, say:
b = np.random.randint(0,2,10)
b =
array([0, 1, 1, 0, 1, 0, 1, 1, 1, 1])
I spent some time trying to find the simple syntax to return only specified colummns in a numpy array in python 3 and finally have it figured out. There are a number of other threads which show more complicated ways to do this, so I thought I would put the simple solution here. This will be very obvious to more experienced python users, but for a beginner like me, it would have been useful.
The simplest way is:
new_matrix = a[:,b==1]
which yields:
new_matrix =
array([[9, 1, 5, 1, 7, 6, 5],
[4, 2, 8, 5, 5, 7, 5],
[8, 7, 3, 8, 8, 8, 3],
[4, 4, 9, 7, 1, 6, 8],
[3, 2, 7, 8, 8, 4, 9],
[5, 6, 6, 1, 4, 4, 5],
[4, 3, 8, 2, 2, 8, 6],
[5, 4, 9, 9, 2, 5, 6],
[5, 9, 3, 5, 7, 4, 8],
[1, 3, 8, 2, 6, 6, 7]])
This would have saved me a lot of time.

Made typo, Python function still works. Why?

I've been learning programming and Python for about a month now using Udacity. For one of the questions we are supposed to write a function that checks if a sudoku list passed in is valid.
In the for loop below, I wanted to iterate through row and col at the same time with both the original and transposed list using zip() but mistakenly left in row in the second half of my or statement. I ran it and to my surprise, it still continued to return a correct answer.
def check_sudoku(array):
is_sudoku = True
reference = range(1, len(array) + 1)
transposed = zip(array)
for row, col in zip(array, transposed):
if sorted(row) != reference or sorted(row) != reference:
is_sudoku = False
break
return is_sudoku
My guess is it's because I defined is_sudoku = True by default, and I'm comparing rows with a reference list so it catches invalid values even if my transpose didn't work. When I replaced the second row with col though, it broke.
My question is, is my guess right? If not, why does this code work and how could I better write this?
Thanks! (Pasted on codepad as well if you want to see what lists I passed in - http://codepad.org/IXDlZuUu)
If the correct value was False, then your function works because at some point sorted(row) != reference. As for rewriting it, I'd think something like this would be more clear:
def check_sudoku(array):
reference = range(1, len(array) + 1)
transposed = zip(array)
for row, col in zip(array, transposed):
if sorted(row) != reference or sorted(row) != reference:
return False
return True
Additionally, it's pretty hard for me to see why you do transposed = zip(array) and then zip(array, transposed). As far as I can tell that just takes a list like [1, 2, 3] and turns it into [(1, (1,)), (2, (2,)), (3, (3,))].
If you are looking to iterate through the rows and columns, here's one method that works.
>>> rows = incorrect
>>> cols = [[row[i] for i in range(len(rows[0]))] for row in rows]
>>> cols = [[row[i] for row in rows] for i in range(len(row))]
>>> cols
[[4, 6, 3, 9, 7, 8, 1, 5, 2], [1, 5, 9, 6, 3, 2, 4, 8, 7], [2, 8, 7, 4, 5, 1, 9, 3, 6], [3, 9, 5, 2, 1, 7, 6, 4, 8], [6, 4, 2, 3, 8, 9, 5, 7, 1], [7, 1, 8, 5, 4, 6, 3, 2, 9], [8, 3,
1, 7, 6, 4, 2, 9, 5], [5, 2, 6, 8, 9, 3, 7, 1, 4], [1, 7, 4, 1, 2, 5, 8, 6, 3]]
>>> rows
[[4, 1, 2, 3, 6, 7, 8, 5, 1], [6, 5, 8, 9, 4, 1, 3, 2, 7], [3, 9, 7, 5, 2, 8, 1, 6, 4], [9, 6, 4, 2, 3, 5, 7, 8, 1], [7, 3, 5, 1, 8, 4, 6, 9, 2], [8, 2, 1, 7, 9, 6, 4, 3, 5], [1, 4,
9, 6, 5, 3, 2, 7, 8], [5, 8, 3, 4, 7, 2, 9, 1, 6], [2, 7, 6, 8, 1, 9, 5, 4, 3]]

Categories

Resources