Related
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]])
my_function must expand a 1D numpy array to a 2D numpy array, with the 2nd axis containing the slices of length starting from the first index until the end. Example:
import numpy as np
a = np.arange(10)
print (my_function(a, length=3))
Expected output
array([[0, 1, 2],
[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
[4, 5, 6],
[5, 6, 7],
[6, 7, 8],
[7, 8, 9]])
I can achieve this using a for loop, but I was wondering if there is a numpy vectorization technique for this.
def my_function(a, length):
b = np.zeros((len(a)-(length-1), length))
for i in range(len(b)):
b[i] = a[i:i+length]
return b
If you're careful with the math and heed the warningin the docs, you can use np.lib.stride_tricks.as_strided(). You need to calculate the correct dimensions for your array so you don't overflow. Also note that as_strided() shares memory, so you will multiple references to the same memory in the final output. (You can of course, copy this to a new array).
>> import numpy as np
>> def my_function(a, length):
stride = a.strides[0]
l = len(a) - length + 1
return np.lib.stride_tricks.as_strided(a, (l, length), (stride,stride) )
>> np.array(my_function(np.arange(10), 3))
array([[0, 1, 2],
[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
[4, 5, 6],
[5, 6, 7],
[6, 7, 8],
[7, 8, 9]])
>> np.array(my_function(np.arange(15), 7))
array([[ 0, 1, 2, 3, 4, 5, 6],
[ 1, 2, 3, 4, 5, 6, 7],
[ 2, 3, 4, 5, 6, 7, 8],
[ 3, 4, 5, 6, 7, 8, 9],
[ 4, 5, 6, 7, 8, 9, 10],
[ 5, 6, 7, 8, 9, 10, 11],
[ 6, 7, 8, 9, 10, 11, 12],
[ 7, 8, 9, 10, 11, 12, 13],
[ 8, 9, 10, 11, 12, 13, 14]])
How about this function?
import numpy as np
def my_function(a, length):
result = []
for i in range(length):
result.append(a + i)
return np.vstack(result).T[:len(a) - length + 1]
a = np.arange(10)
length = 3
my_function(a, length)
I'm looking for a short readable way to select some rows of an 2D numpy.ndarray, where the first number of each row is in some list.
Example:
>>> index
[4, 8]
>>> data
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
So in this case i only need
array([[ 4, 5, 6, 7],
[8, 9, 10, 11]])
because the first numbers of these rows are 4 and 8 which are listed in index.
Basically im looking for something like:
data[data[:,0] == i if i in index]
which of course is not working.
You can use np.isin to check, then index as usual:
idx = [4, 8]
data = np.array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
>>> data[np.isin(data[:,0], idx)]
array([[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
If you want to use a list comprehension, here's how (isin is undoubtably better for this usage case, though):
>>> np.array([e for e in data if e[0] in index])
array([[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
I'm struggling to perform the below operation on a numpy vector.
I want to take previous_n samples from vector finishing at indices.
It's like I want to perform a np.take with slicing of the previous_n samples.
Example:
import numpy as np
vector = np.array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
# number of previous samples
previous_n = 3
indices = np.array([ 5, 7, 12])
result
array([[ 3, 4, 5],
[ 5, 6, 7],
[10, 11, 12]])
Ok, this seems to do what I want. Found here
def stack_slices(arr, previous_n, indices):
all_idx = indices[:, None] + np.arange(previous_n) - (previous_n - 1)
return arr[all_idx]
>>> stack_slices(vector, 3, indices)
array([[ 3, 4, 5],
[ 5, 6, 7],
[10, 11, 12]])
I have a 2D array like this:
a = [[1,2,3,4,5,6,7,8,9,10],[1,2,3,4,5,6,7,8,9,10]]
is there a way to cut them per row in ah pythonic way?
So the result will be:
[[1,1],[2,2],[3,3],[4,4],[5,5],[6,6],[7,7],[8,8],[9,9],[10,10]]
use .T
a = np.array([[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]])
a.T
array([[ 1, 1],
[ 2, 2],
[ 3, 3],
[ 4, 4],
[ 5, 5],
[ 6, 6],
[ 7, 7],
[ 8, 8],
[ 9, 9],
[10, 10]])