Related
This question already has answers here:
How do I compute all possibilities for an array of numbers/bits (in python, or any language for that matter)
(5 answers)
Closed 2 years ago.
I am trying to achieve the following. I have a 2D array, which is of a 4x4 dimension. I want to get all possibilities, where I can insert a single 1 instead of a zero, and return an array, which contains all of these possibilities
So if we take:
[[0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
would result in:
[[1, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
[[0, 1, 1, 0], [0, 0, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
[[0, 1, 0, 1], [0, 0, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
...
There would be a total of 14 entries in the resulting array, since there were 14 zeroes in the input array.
The problem is, that the code I have currently should work, as far as I understand, but I can't seem to get where it goes wrong.
def getPossibilities(arr):
p = []
for i in range(4):
for j in range(4):
if arr[i][j] == 0:
p.append(arr)
p[-1][i][j]=1
return p
for i in getPossibilities([[0,1,0,0],[0,0,1,0],[0,0,0,0],[0,0,0,0]]):
print(i)
This results in 14 arrays of solid ones.
I included the way I check the results, in case there is an error there. I also tried with first copying the arr array into a temporary one, then make the changes, but to no avail.
What goes wrong here? I cannot seem to find an answer. Also, is there a more elegant and faster way of doing this? It would be really beneficial for my usecase.
Thank you very much in advance!
This is somewhat tricky but since you have a list of lists, the copy won't work and you will be changing the array every time, what you need is deepcopy:
import copy
def getPossibilities(arr):
p = []
for i in range(4):
for j in range(4):
if arr[i][j] == 0:
tmp = copy.deepcopy(arr)
tmp[i][j]=1
p.append(tmp)
return p
for i in getPossibilities([[0,1,0,0],[0,0,1,0],[0,0,0,0],[0,0,0,0]]):
print(i)
[[1, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
[[0, 1, 1, 0], [0, 0, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
[[0, 1, 0, 1], [0, 0, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
[[0, 1, 0, 0], [1, 0, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
[[0, 1, 0, 0], [0, 1, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
[[0, 1, 0, 0], [0, 0, 1, 1], [0, 0, 0, 0], [0, 0, 0, 0]]
[[0, 1, 0, 0], [0, 0, 1, 0], [1, 0, 0, 0], [0, 0, 0, 0]]
[[0, 1, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 0]]
[[0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 0, 0]]
[[0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1], [0, 0, 0, 0]]
[[0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 0], [1, 0, 0, 0]]
[[0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 0], [0, 1, 0, 0]]
[[0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 0], [0, 0, 1, 0]]
[[0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 0], [0, 0, 0, 1]]
I have a numpy array with the shape (6, 3, 4) that I'd like to fill with an ascending sequence of numbers so that the resulting array is this:
array([[[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]],
[[1, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]],
[[2, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]],
[[3, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]],
[[4, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]],
[[5, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]]], dtype=uint8)
I do not want to use a loop, if possible.
I've tried the following with no luck:
import numpy as np
new_row = np.zeros([6, 3, 4], dtype=np.uint8)
new_row[:,0:1,0:1] = range(6)
which results in ValueError: could not broadcast input array from shape (6) into shape (6,1,1)
Any help appreciated
I would like to initialize a multidimensional list capable of storing an object for every minute since year 1950-2050.
Something like:
minute = [None]*61
hour = [minute]*25
day = [hour]
month = [day]
data = [month]*100
So you can do:
data[89][1][29][23][55] = 'It was a good minute the one from January 29th in 1989 when it was 23:55'
How would be such a multidimensional list be initialized in Python? Would it be an actual different object than the one created with the above code?
Initially the multidimensional list would contain objects None.
Python 2.7
Following answer I tried:
# Data structure
minute = 60
hour = 24
day = 31
month = 12
year = 100
test = [[[[[None for _minute in range(minute)] for _hour in range(hour)] for _day in range(day)] for _month in range(month)] for _year in range(year)]
But it seems too much for multidimensional lists, as I get "Killed" when trying to execute this.
I also don't recommend this, but you could use a numpy.chararray for this:
import numpy as np
arr = np.chararray((100, 12, 31, 24, 60, 60), itemsize=100)
arr[52, 7, 12, 12, 44, 54] = 'year 1950+52, 7th month, 12th day, 12th hour, 44th minute, 54th second'
I'm not exactly sure what your desired structure is, but the string I inserted into the array should explain the structure I proposed, and you can change it however you need. Note that itemsize limits how many characters you can put in at any index.
Again, with a caveat that this is not necessarily the most efficient thing in the world to do, but if you wish to store lists of ints and/or floats in that array (as per your comment), one way to do it would be to convert that list to strings, and then when retrieving it, re-transform back to a list:
data_to_insert = [1,2,3,4.5]
# store as string
arr[52, 7, 12, 12, 44, 54] = ','.join(map(str, data_to_insert))
# retrieve
arr[52, 7, 12, 12, 44, 54].decode('utf-8').split(',')
This should be pretty fast
Though i won't recommend it,
A multi dimentional empty list can be created by using list comprehension:
> >>> a = 4 #Width of elements
> >>> b = 6 #Width of main list container
>>>>> c = 4
>>>>> d = 3
> >>> l = [[[[0 for k in range(d) ] for z in range(c)] for x in range(a)] for y in range(b)]
> >>> [[[[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, 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, 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]]]]
Keep replacing 0 with list comprehensions to add more dimentions.
So I have several 3D arrays that I need to add together. Each array consists of entries with either 0 or 1. All arrays also have the same dimension. Now, when I add these arrays together some of the values overlap (which they do). However, I just need to know how the structure of the total combined array is, which means that I don't need the values 1, 2 or 3 when 2 or 3 arrays have overlapped. This also just need to be one, and of course, wherever there is a zero, the value zero just need to remain zero.
So basically what I have is:
array1 =
[[[1, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 1, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 1], [1, 1, 1], [0, 0, 0]]]
array2 =
[[[1, 0, 0], [0, 1, 0], [0, 0, 0]],
[[0, 0, 0], [1, 1, 0], [0, 0, 0]],
[[0, 0, 1], [0, 1, 0], [0, 0, 0]]]
So when adding them together I get:
array_total = array1 + array2 =
[[[2, 0, 0], [0, 1, 0], [0, 0, 0]],
[[0, 1, 0], [1, 1, 0], [0, 0, 0]],
[[0, 0, 2], [1, 2, 1], [0, 0, 0]]]
Where I actually want it to give me:
array_total = array1 + array2 =
[[[1, 0, 0], [0, 1, 0], [0, 0, 0]],
[[0, 1, 0], [1, 1, 0], [0, 0, 0]],
[[0, 0, 1], [1, 1, 1], [0, 0, 0]]]
So can anyone give me a hint to how this is done ?
(Assuming those are numpy arrays, or array1 + array2 would behave differently).
If you want to "change all positive values to 1", you can do this
array_total[array_total > 0] = 1
But what you actually want is an array that has a 1 where array1 or array2 has a 1, so just write it directly like that:
array_total = array1 | array2
Example:
>>> array1 = np.array([[[1, 0, 0], [0, 0, 0], [0, 0, 0]],
... [[0, 1, 0], [0, 0, 0], [0, 0, 0]],
... [[0, 0, 1], [1, 1, 1], [0, 0, 0]]])
>>> array2 = np.array([[[1, 0, 0], [0, 1, 0], [0, 0, 0]],
... [[0, 0, 0], [1, 1, 0], [0, 0, 0]],
... [[0, 0, 1], [0, 1, 0], [0, 0, 0]]])
>>> array1 | array2
array([[[1, 0, 0], [0, 1, 0], [0, 0, 0]],
[[0, 1, 0], [1, 1, 0], [0, 0, 0]],
[[0, 0, 1], [1, 1, 1], [0, 0, 0]]])
I've got a large 3d numpy array which consists of ones and zeros. I would like to use the scipy.ndimage.label tool to label the features in each sub-array (2d).
A subset of the 3d-array looks like:
import numpy as np
from scipy.ndimage import label
subset = np.array([[[1, 0, 0],
[1, 0, 1],
[0, 0, 0]],
[[0, 0, 0],
[1, 0, 1],
[0, 0, 1]],
[[0, 0, 0],
[1, 0, 0],
[0, 1, 1]],
[[0, 0, 0],
[1, 0, 0],
[1, 1, 1]]], dtype=uint8)
When I use the label tool on a small part of this subset is works correct:
>>>label(subset[0:3])
(array([[[1, 0, 0],
[1, 0, 2],
[0, 0, 0]],
[[0, 0, 0],
[1, 0, 2],
[0, 0, 2]],
[[0, 0, 0],
[1, 0, 0],
[0, 2, 2]]]), 2)
However, when I use the entire subset the label tool is not working properly:
>>>label(subset)
(array([[[1, 0, 0],
[1, 0, 1],
[0, 0, 0]],
[[0, 0, 0],
[1, 0, 1],
[0, 0, 1]],
[[0, 0, 0],
[1, 0, 0],
[0, 1, 1]],
[[0, 0, 0],
[1, 0, 0],
[1, 1, 1]]]), 1)
Any ideas how this problem can be tackled?
ps.
The complete array which I am trying to label consists of 350219 2d arrays.
I answered this question with the help of dan-man.
I had to define a new 3D structure for the label tool:
import numpy as np
from scipy.dimage import label
str_3D = np.array([[[0, 0, 0],
[0, 0, 0],
[0, 0, 0]],
[[0, 1, 0],
[1, 1, 1],
[0, 1, 0]],
[[0, 0, 0],
[0, 0, 0],
[0, 0, 0]]], dtype='uint8')
Now the label returns the following for my subset:
>>> label(subset, structure=str_3D)
# outputs:
(array([[[1, 0, 0],
[1, 0, 2],
[0, 0, 0]],
[[0, 0, 0],
[3, 0, 4],
[0, 0, 4]],
[[0, 0, 0],
[5, 0, 0],
[0, 6, 6]],
[[0, 0, 0],
[7, 0, 0],
[7, 7, 7]]]), 7)