Can I "rotate" and slice in one numpy operation? - python

I have data like this:
[[[1, 2, 3]
[4, 5, 6]]
[[7, 8, 9]
[0, 1, 2]]]
and I need to get it into this "shape":
[[[1, 4], [2, 5], [3, 6]]
[[7, 0], [8, 1], [9, 2]]]
The best method I have for doing this so far is:
for i in range(2):
pairs = tuple(
array[i, :, j] for j in range(3) # ---axis-2-length---
)
print(pairs)
to produce:
([1, 4], [2, 5], [3, 6])
([7, 0], [8, 1], [9, 2])
While this gets the job done, that's a lot of interpreted Python, especially as these datasets grow. So I was wondering if I could somehow get this done with fancy indexing or transposition or something else my numpy-fu is not yet strong enough to conceive of myself.
Does anyone know how to get this done more elegantly with numpy?

Transposition with ndarray.transpose will work here.
>>> x.transpose(0, 2, 1)
array([[[1, 4],
[2, 5],
[3, 6]],
[[7, 0],
[8, 1],
[9, 2]]])

Related

Reshaping a list containing an array in Python

I want to reshape the list Ii to (1,11,2) but I am getting an error. I present the expected output.
import numpy as np
Ii=[np.array([[0, 2],
[2, 4],
[2, 5],
[2, 6],
[3, 1],
[3, 7],
[4, 5],
[4, 6],
[5, 3],
[5, 7],
[6, 5]])]
Y=Ii[0].shape
Ii=Ii[0].reshape(1,Y)
The error is
in <module>
Ii=Ii[0].reshape(1,Y)
TypeError: 'tuple' object cannot be interpreted as an integer
The expected output is
array([[[0, 2],
[2, 4],
[2, 5],
[2, 6],
[3, 1],
[3, 7],
[4, 5],
[4, 6],
[5, 3],
[5, 7],
[6, 5]]])
np.newaxis can be used here to reshape the array.
Ii[0][np.newaxis,:]
or you can use reshaping after unpacking tuple.
Ii[0].reshape([1, *Y])
Try this:
Ii = Ii[0].reshape(1, Y[0], Y[1])

Faster and more pythonic way to reproduce unique set of unordered random numbers inside nested list

I wanted to create a domino game. I'm in the beginning of my journey to become a python dev.
I have made enough progress but I'm wondering if i could refactor my unique set generator function more elegant - pythonic and shorter.
This is my function and i think it is working as it should be. All the other functions in the program are depended on this.
The main job of the function is creating a list of unique set of two random numbers (0-6(including)) range and all of those lists are inside a list.
For ex. [1,2] and [2,1] are the same and should appear only once in the final array.
from random import randrange
length = 28
def unique_set_generator(set_size):
unique_set = set()
main_set = []
while len(unique_set) != set_size:
x, y = randrange(7), randrange(7)
if (x, y) not in unique_set and (y, x) not in unique_set:
unique_set.add((x, y))
set_to_list = list(unique_set)
for i in range(set_size):
main_set.append(list(set_to_list[i]))
return main_set
print(unique_set_generator(length))
Outcome:
[[4, 3], [5, 4], [2, 2], [1, 0], [1, 3], [6, 5], [4, 2], [3, 3], [5, 0], [3, 6], [5, 3], [1, 2], [0, 4], [1, 5], [6, 1], [6, 4], [3, 2], [5, 2], [4, 4], [5, 5], [0, 0], [1, 1], [0, 3], [2, 0], [1, 4], [2, 6], [6, 0], [6, 6]]
Use the tools Python provides:
import random
dominos = [(i,j) for i in range(7) for j in range(i,7)]
print(dominos)
random.shuffle(dominos)
print(dominos)

Concatenating 3 multidimensional arrays in Python

I have three arrays I1,I2,I3 with shape (1,9,2). I am trying to append but there is an error. The new array should have shape (3,9,2)
import numpy as np
I1 = np.array([[[0, 2],
[2, 3],
[2, 5],
[3, 4],
[3, 6],
[4, 1],
[4, 7],
[5, 6],
[6, 7]]])
I2 = np.array([[[1, 1],
[2, 3],
[2, 5],
[3, 4],
[3, 6],
[4, 1],
[4, 7],
[5, 6],
[6, 7]]])
I3 = np.array([[[2, 2],
[2, 3],
[2, 5],
[3, 4],
[3, 6],
[4, 1],
[4, 7],
[5, 6],
[6, 7]]])
I=np.append(I1,I2,I3,axis=0)
The error is
in <module>
Iit=np.append(Iit1,Iit2,Iit3,axis=0)
File "<__array_function__ internals>", line 4, in append
TypeError: _append_dispatcher() got multiple values for argument 'axis'
Use I=np.concatenate([I1,I2,I3],axis=0) rather than append. Append does what you'd expect from a list (and try not to use it in numpy, anyway, for memory allocation reasons!)`
A different way from #Dominik is
I = np.stack((I1,I2,I3))
stack creates a new axis.

Calculate all the possible sums of rolling x die with y sides

I'm writing a function that helps me calculate the possible outcomes of summing a variable numbe of die with a variable number of sides (for instance, the total sum of two six-sided die and a four sided die) and I've been stumped for a while.
Rolling two three sided die for instance should output an array with all 9 possible combinations:
[[1,1],
[1,2],
[1,3],
[2,1],
(etc.)
[3,2],
[3,3]]
And I can't quite figure it out. I've managed to generate range to enumerate on, but I can't quite make it.
dice = [6,6]
diceRanges = [range(0, die) for die in dice]
diceIndex = [0 for die in dice]
outcomes = []
for idx, rng in enumerate(diceRanges):
for var in rng:
diceIndex[idx] = var
outcomes.append([val for val in diceIndex])
outcomes
I've seen some things around but never quite as simple as it seems to be.
Cheers
It's simple if you use itertools:
import itertools
outcomes = list(itertools.product(*diceRanges))
Using numpy only
dice_sides = 6
dices_values = np.arange(1,dice_sides+1)
outcome = np.dstack(np.meshgrid(dices_values, dices_values)).reshape(-1,2)
Out[313]:
array([[1, 1],
[2, 1],
[3, 1],
[4, 1],
[5, 1],
[6, 1],
[1, 2],
[2, 2],
[3, 2],
[4, 2],
[5, 2],
[6, 2],
[1, 3],
[2, 3],
[3, 3],
[4, 3],
[5, 3],
[6, 3],
[1, 4],
[2, 4],
[3, 4],
[4, 4],
[5, 4],
[6, 4],
[1, 5],
[2, 5],
[3, 5],
[4, 5],
[5, 5],
[6, 5],
[1, 6],
[2, 6],
[3, 6],
[4, 6],
[5, 6],
[6, 6]])

declaring and initialising 2d array in python

I am declaring multidimensional array in python
Nbrs[23][2] = [[1, 1], [1, 2], [2, 1],
[2, 3], [3, 2], [1, 3],
[3, 1], [1, 4], [3, 4],
[4, 3], [4, 1], [1, 5],
[2, 5], [3, 5], [4, 5],
[5, 4], [5, 3], [5, 2],
[5, 1], [1, 6], [5, 6],
[6, 5], [6, 1]
]
It gives me error as:
NameError: name 'Nbrs' is not defined
I cannot declare 2 dimensional array in python by this way?
Assignment statement:
Nbrs[23][2] = [[1, 1], [1, 2], [2
# ^ ^ you can't index Nbrs before it created
should be:
Nbrs = [[1, 1], [1, 2], [2
# now after this statement, Nbrs a list of list you can access
# its elements useng `Nbrs[i][j]` for i < len(Nbrs) and j < 2
I think you confuses because of C, C++ declarations!
You don't need to specify the dimensions when defining lists in python. When you type Nbrs[23][2] python is trying to find what's at [23][2] in Nbrs but in this case Nbrs doesn't exist because you are trying to define it for the first time here.
Instead do this:
Nbrs = [[1, 1], [1, 2], [2, 1], ....
That's not the right syntax. You don't need to include anything about the variable's type on the left-hand side; in particular, drop the dimensions.
Nbrs = [[1, 1], [1, 2], [2, 1], [2, 3], [3, 2], [1, 3], [3, 1], [1, 4], [3, 4], [4, 3], [4, 1], [1, 5], [2, 5], [3, 5], [4, 5], [5, 4], [5, 3], [5, 2], [5, 1], [1, 6], [5, 6], [6, 5], [6, 1]]
What you've written tries to assign to an element of Nbrs, which doesn't exist yet.

Categories

Resources