I want to replace an item in a numpy array composed of 0 and 1.
I want to replace 1 with the list [0,1] and the 0 with the list [1,0].
I found the function numpy.where(), but it doesn't work with lists.
Is there a function or something similar to do the equivalent for numpy.where(vector==1,[0,1], [1,0]) ?
Simple indexing should do the job:
In [156]: x = np.array([0,1,0,0,1,1,0])
In [157]: y = np.array([[1,0],[0,1]])
In [158]: y[x]
Out[158]:
array([[1, 0],
[0, 1],
[1, 0],
[1, 0],
[0, 1],
[0, 1],
[1, 0]])
And just to be sure this is a general solution, not some 'boolean' fluke
In [162]: x = np.array([0,1,0,0,1,2,2])
In [163]: y = np.array([[1,0],[0,1],[1,1]])
In [164]: y[x]
Out[164]:
array([[1, 0],
[0, 1],
[1, 0],
[1, 0],
[0, 1],
[1, 1],
[1, 1]])
You can actually use where for that if you wish:
>>> import numpy as np
>>> vector = np.random.randint(0, 2, (8, 8))
>>> vector
array([[1, 0, 0, 0, 0, 0, 1, 1],
[1, 1, 0, 1, 0, 0, 0, 1],
[1, 0, 0, 1, 1, 1, 0, 0],
[1, 0, 1, 1, 0, 0, 0, 0],
[0, 1, 0, 1, 1, 1, 1, 1],
[1, 0, 1, 1, 0, 0, 0, 0],
[0, 1, 1, 0, 1, 1, 0, 0],
[1, 1, 1, 1, 1, 1, 0, 0]])
>>> np.where(vector[..., None] == 1, [0,1], [1,0])
# btw. if vector has only 0 and 1 entries you can leave out the " == 1 "
array([[[0, 1],
[1, 0],
[1, 0],
[1, 0],
[1, 0],
[1, 0],
[0, 1],
[0, 1]],
[[0, 1],
[0, 1],
[1, 0],
[0, 1],
[1, 0],
[1, 0],
[1, 0],
etc.
Looks like you want to make one-hot vector encoding:
a = np.array([1, 0, 1, 1, 0]) # initial array
b = np.zeros((len(a), 2)) # where 2 is number of classes
b[np.arange(len(a)), a] = 1
print(b)
result:
array([[ 0., 1.],
[ 1., 0.],
[ 0., 1.],
[ 0., 1.],
[ 1., 0.]])
Since it's not possible to grow the array dynamically in NumPy, you've to convert the array to list, do the substitution as desired, and then convert the result back to NumPy array like:
In [21]: vector = np.array([0, 0, 1, 0, 1])
In [22]: vlist = vector.tolist()
In [23]: vlist
Out[23]: [0, 0, 1, 0, 1]
In [24]: new_list = [[1, 0] if el == 0 else [0, 1] for idx, el in enumerate(vlist)]
In [25]: result = np.array(new_list)
In [26]: result
Out[26]:
array([[1, 0],
[1, 0],
[0, 1],
[1, 0],
[0, 1]])
If your 1D array is not that large enough, then list comprehension is not that bad of an approach.
hpaulj's answer would be the ideal way of doing this. An alternative is to reshape your original numpy array, and apply your standard np.where() operation.
import numpy as np
x = np.array([0,1,0,0,1,1,0])
x = np.reshape(x,(len(x),1))
# Equivalently, if you want to be explicit:
# x = np.array([[e] for e in x])
print np.where(x==1,[1,0],[0,1])
# Result:
array([[0, 1],
[1, 0],
[0, 1],
[0, 1],
[1, 0],
[1, 0],
[0, 1]])
Related
import itertools
x = [[0,0],[1,1]]
list(itertools.product(x,x))
produces
[([0, 0], [0, 0]), ([0, 0], [1, 1]), ([1, 1], [0, 0]), ([1, 1], [1, 1])]
But I'm looking for something that produces
[[0, 0, 0, 0], [0, 0, 1, 1], [1, 1, 0, 0], [1, 1, 1, 1]]
itertools.product is giving you that answer, you just have to concatenate the lists
[a + b for a, b in [([0, 0], [0, 0]), ([0, 0], [1, 1]), ([1, 1], [0, 0]), ([1, 1], [1, 1])]]
# [[0, 0, 0, 0], [0, 0, 1, 1], [1, 1, 0, 0], [1, 1, 1, 1]]
In that case, you can easily do without using itertools, using list comprehension:
x = [[0, 0], [1, 1]]
output = [a + b for b in x for a in x]
# [[0, 0, 0, 0], [1, 1, 0, 0], [0, 0, 1, 1], [1, 1, 1, 1]]
the equivalent without list comprehension would be:
output = []
for a in x:
for b in x:
output.append(a + b)
print(output)
You can use np.reshape if you are considering numpy array.
np.reshape(list(itertools.product(x,x)),(4,4))
Out[28]:
array([[0, 0, 0, 0],
[0, 0, 1, 1],
[1, 1, 0, 0],
[1, 1, 1, 1]])
I have an array of numbers between 0 and 3 and I want to create a 2D array of their binary digits.
in the future may be I need to have array of numbers between 0 and 7 or 0 to 15.
Currently my array is defined like this:
a = np.array([[0], [1], [2], [3]], dtype=np.uint8)
I used numpy unpackbits function:
b = np.unpackbits(a, axis=1)
and the result is this :
array([[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 1, 1]], dtype=uint8)
As you can see it created a 2d array with 8 items in column while I'm looking for 2 columns 2d array.
here is my desired array:
array([[0, 0],
[0, 1],
[1, 0],
[1, 1]])
Is this related to data type uint8 ?
what is your idea?
One way of approaching the problem is to just adapt your b to match your desired output via a simple slicing, similarly to what suggested in #GrzegorzSkibinski answer:
import numpy as np
def gen_bits_by_val(values):
n = int(max(values)).bit_length()
return np.unpackbits(values, axis=1)[:, -n:].copy()
print(gen_bits_by_val(a))
# [[0 0]
# [0 1]
# [1 0]
# [1 1]]
Alternatively, you could create a look-up table, similarly to what suggested in #WarrenWeckesser answer, using the following:
import numpy as np
def gen_bits_by_num(n):
values = np.arange(2 ** n, dtype=np.uint8).reshape(-1, 1)
return np.unpackbits(values, axis=1)[:, -n:].copy()
bits2 = gen_bits_by_num(2)
print(bits2)
# [[0 0]
# [0 1]
# [1 0]
# [1 1]]
which allows for all kind of uses thereby indicated, e.g.:
bits4 = gen_bits_by_num(4)
print(bits4[[1, 3, 12]])
# [[0 0 0 1]
# [0 0 1 1]
# [1 1 0 0]]
EDIT
Considering #PaulPanzer answer the line:
return np.unpackbits(values, axis=1)[:, -n:]
has been replaced with:
return np.unpackbits(values, axis=1)[:, -n:].copy()
which is more memory efficient.
It could have been replaced with:
return np.unpackbits(values << (8 - n), axis=1, count=n)
with similar effects.
You can use the count keyword. It cuts from the right so you also have to shift bits before applying unpackbits.
b = np.unpackbits(a<<6, axis=1, count=2)
b
# array([[0, 0],
# [0, 1],
# [1, 0],
# [1, 1]], dtype=uint8)
This produces a "clean" array:
b.flags
# C_CONTIGUOUS : True
# F_CONTIGUOUS : False
# OWNDATA : True
# WRITEABLE : True
# ALIGNED : True
# WRITEBACKIFCOPY : False
# UPDATEIFCOPY : False
In contrast, slicing the full 8-column output of unpackbits is in a sense a memory leak because the discarded columns will stay in memory as long as the slice lives.
You can truncate b to keep just the columns since the first column with 1:
b=b[:, int(np.argwhere(b.max(axis=0)==1)[0]):]
For such a small number of bits, you can use a lookup table.
For example, here bits2 is an array with shape (4, 2) that holds the bits of the integers 0, 1, 2, and 3. Index bits2 with the values from a to get the bits:
In [43]: bits2 = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
In [44]: a = np.array([[0], [1], [2], [3]], dtype=np.uint8)
In [45]: bits2[a[:, 0]]
Out[45]:
array([[0, 0],
[0, 1],
[1, 0],
[1, 1]])
This works fine for 3 or 4 bits, too:
In [46]: bits4 = np.array([[0, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0], [0, 0, 1, 1], [0, 1, 0, 0], [
...: 0, 1, 0, 1], [0, 1, 1, 0], [0, 1, 1, 1], [1, 0, 0, 0], [1, 0, 0, 1], [1, 0, 1, 0], [1, 0,
...: 1, 1], [1, 1, 0, 0], [1, 1, 0, 1], [1, 1, 1, 0], [1, 1, 1, 1]])
In [47]: bits4
Out[47]:
array([[0, 0, 0, 0],
[0, 0, 0, 1],
[0, 0, 1, 0],
[0, 0, 1, 1],
[0, 1, 0, 0],
[0, 1, 0, 1],
[0, 1, 1, 0],
[0, 1, 1, 1],
[1, 0, 0, 0],
[1, 0, 0, 1],
[1, 0, 1, 0],
[1, 0, 1, 1],
[1, 1, 0, 0],
[1, 1, 0, 1],
[1, 1, 1, 0],
[1, 1, 1, 1]])
In [48]: x = np.array([0, 1, 5, 14, 9, 8, 15])
In [49]: bits4[x]
Out[49]:
array([[0, 0, 0, 0],
[0, 0, 0, 1],
[0, 1, 0, 1],
[1, 1, 1, 0],
[1, 0, 0, 1],
[1, 0, 0, 0],
[1, 1, 1, 1]])
I'd need to know the most efficient way for the following case. There is a numpy.ndarray of shape 11k*11k for which I need to force all elements of some rows to be zero given a binary numpy array of shape 11k. A toy example could be described as follows:
Inputs:
x = np.array([[2, 1, 1, 2],
[0, 2, 1, 0],
[1, 0, 1, 1],
[2, 2, 1, 0]])
ref = np.array([0, 1, 1, 0])
Output:
y = ([[0, 0, 0, 0],
[0, 2, 1, 0],
[1, 0, 1, 1],
[0, 0, 0, 0]])
Use this -
y = np.multiply(x.T,ref).T
array([[0, 0, 0, 0],
[0, 2, 1, 0],
[1, 0, 1, 1],
[0, 0, 0, 0]])
This is the list of matrices;
[matrix([[1, 0],
[1, 0],
[1, 0],
[1, 0]]),
matrix([[0, 0, 0, 0],
[1, 1, 1, 1]]),
matrix([[0, 1],
[0, 1],
[0, 1],
[0, 1]]),
matrix([[0, 0, 0, 0],
[1, 1, 1, 1]]),
matrix([[1, 1, 1, 1],
[0, 0, 0, 0]])]
and I want to check if a matrix is already inside the list example;
a = matrix([[0, 0, 0, 1],
[1, 1, 1, 0]])
So if a is in m then print True else print False
I assume you are using NumPy. If this is the case, don't use np.matrix, use np.array. np.matrix exists almost exclusively for legacy reasons and has undesirable features.
You can use any with a generator comprehension and np.array_equal. This will short-circuit to True if the array is found in the input list, otherwise return False.
import numpy as np
L = [np.array([[1, 0], [1, 0], [1, 0], [1, 0]]),
np.array([[0, 0, 0, 0], [1, 1, 1, 1]]),
np.array([[0, 1], [0, 1], [0, 1], [0, 1]]),
np.array([[0, 0, 0, 0], [1, 1, 1, 1]]),
np.array([[1, 1, 1, 1], [0, 0, 0, 0]])]
A = np.array([[0, 0, 0, 1], [1, 1, 1, 0]])
res = any(np.array_equal(A, i) for i in L) # False
I have a ndarray, and I want to set all the non-maximum elements in the last dimension to be zero.
a = np.array([[[1,8,3,4],[6,7,10,6],[11,12,15,4]],
[[4,2,3,4],[4,7,9,8],[41,14,15,3]],
[[4,22,3,4],[16,7,9,8],[41,12,15,43]]
])
print(a.shape)
(3,3,4)
I can get the indexes of maximum elements by np.argmax():
b = np.argmax(a, axis=2)
b
array([[1, 2, 2],
[0, 2, 0],
[1, 0, 3]])
Obviously, b has 1 dimension less than a. Now, I want to get a new 3-d array that has all zeros except for where the maximum values are.
I want to get this array:
np.array([[[0,1,0,0],[0,0,1,0],[0,0,1,0]],
[[1,0,0,1],[0,0,1,0],[1,0,0,0]],
[[0,1,0,0],[1,0,0,0],[0,0,0,1]]
])
One way to achieve this, I tried creating these temporary arrays
b = np.repeat(b[:,:,np.newaxis], 4, axis=2)
t = np.repeat(np.arange(4).reshape(4,1), 9, axis=1).T.reshape(b.shape)
z = np.zeros(shape=a.shape, dtype=int)
z[t == b] = 1
z
array([[[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 1, 0]],
[[1, 0, 0, 0],
[0, 0, 1, 0],
[1, 0, 0, 0]],
[[0, 1, 0, 0],
[1, 0, 0, 0],
[0, 0, 0, 1]]])
Any idea how to get this in a more efficient way?
Here's one way that uses broadcasting:
In [108]: (a == a.max(axis=2, keepdims=True)).astype(int)
Out[108]:
array([[[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 1, 0]],
[[1, 0, 0, 1],
[0, 0, 1, 0],
[1, 0, 0, 0]],
[[0, 1, 0, 0],
[1, 0, 0, 0],
[0, 0, 0, 1]]])