Concatenate numpy arrays in for loop - python

I've split an image up into 16 figures to plot regression and now I want to join it back together into one image.
I've written a for loop to do this but I'm having trouble understanding the advice from previous questions and where I'm going wrong. Please could someone explain why my input arrays do not have the same number of dimensions.
from scipy import interpolate
allArrays = np.array([])
for i in range(len(a)):
fig = plt.figure()
ax = fig.add_axes([0.,0.,1.,1.])
if np.amax(a[i]) > 0:
x, y = np.where(a[i]>0)
f = interpolate.interp1d(y, x)
xnew = np.linspace(min(y), max(y), num=40)
ynew = f(xnew)
plt.plot(xnew, ynew, '-')
plt.ylim(256, 0)
plt.xlim(0,256)
fig.canvas.draw()
X = np.array(fig.canvas.renderer._renderer)
myArray = color.rgb2gray(X)
print(myArray.shape)
allArrays = np.concatenate([allArrays, myArray])
print(allArrays.shape)
else:
plt.xlim(0,256)
plt.ylim(0,256)
fig.canvas.draw()
X = np.array(fig.canvas.renderer._renderer)
myArray = color.rgb2gray(X)
print(myArray.shape)
allArrays = np.concatenate([allArrays, myArray])
print(allArrays.shape)
i += 1
Output: myArray.shape (480, 640)
Error message: all the input arrays must have same number of dimensions
I'm sure it's really simple but I can't figure it out. Thanks.

In [226]: allArrays = np.array([])
In [227]: allArrays.shape
Out[227]: (0,)
In [228]: allArrays.ndim
Out[228]: 1
In [229]: myArray=np.ones((480,640))
In [230]: myArray.shape
Out[230]: (480, 640)
In [231]: myArray.ndim
Out[231]: 2
1 does not equal 2 in most worlds!
To concatenate with myArray on the default axis 0, allArrays would have to start as np.zeros((0,640), myArray.dtype). After n iterations it would grow to (n*480, 640).
In the linked answer, the new arrays are all 1d, so starting with shape (0,) is ok. But wim's answer is better - collect all arrays in a list, and do one concatenate at the end.
Repeated concatenate in a loop is hard to get right (you have to understand shapes and dimensions), and slower than list appends.

Related

How to stack numpy array along an axis

I have two numpy arrays, one with shape let's say (10, 5, 200), and another one with the shape (1, 200), how can I stack them so I get as a result an array of dimensions (10, 6, 200)? Basically by stacking it to each 2-d array iterating along the first dimension
a = np.random.random((10, 5, 200))
b = np.zeros((1, 200))
I'v tried with hstack and vstack but I get an error in incorrect number of axis
Let's say:
a = np.random.random((10, 5, 200))
b = np.zeros((1, 200))
Let's look at the volume (number of elements) of each array:
The volume of a is 10*5*200 = 10000.
The volume of an array with (10,6,200) is 10*5*200=1200.
That is you want to create an array that has 2000 more elements.
However, the volume of b is 1*200 = 200.
This means a and b can't be stacked.
As hpaulj mentioned in the comments, one way is to define an numpy array and then fill it:
result = np.empty((a.shape[0], a.shape[1] + b.shape[0], a.shape[2]))
result[:, :a.shape[1], :] = a
result[:, a.shape[1]:, :] = b

Insert N matrices with 3 dimensions to a new variable

I need to insert 3-dimensional matrices into a new variable.
I'm trying to do that by:
Creating a 4-dimensional matrix and by promoting the fourth dimension saving the three dimensions respectively.
Sample code:
from python_speech_features import mfcc
import numpy as np
X = np.zeros((0,0,0,0),float) #4-dimensional - (0, 0, 0, 0)
ii = 0
for ii in range 1000:
data, fs = sf.read(curfile[ii])
sig = mfcc(data, fs, winstep=winstep,winlen=winlen,nfft=1024) #size - (49, 13)
sig = sig[:, :, np.newaxis] #add third-dimensional - (49, 13, 1)
X[:,:,:,ii] = sig
Error:
IndexError: index 0 is out of bounds for axis 3 with size 0
Someone can help me with that problem?
You are not creating array in right way. You cannot insert value in axis which have zero length at least specify some length for axis
X = np.zeros((10, 10, 10,1000), float)
print(X.shape)
# (10, 10, 10, 1000)
Now you can set value in whatever axis you want by simply,
X[:, :, :, 2] = 1
# this will simply set value of 3rd axis's 3rd element to 1
Either use np.stack (i think it is the best way of doing it) or create the initial array in its final size:
np.zeros((49,13,1,1000), float)
In your case

python 3 empty graph

I have a problem showing data in a graph. The graph frame appears, but no graph is to be seen. Can you please help ?
I made sure that the dimension of the x axis and the data is the same ... I simply cannot find out why I do not get a graph in return.
Thank you very much in advance.
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
n = 1000
theta = 0.8
d = np.sqrt(1-theta**2)
def p(x,y):
"Stochastic kernel for the TAR model"
return norm().pdf((y-theta*np.abs(x))/d)/d
Z = norm().rvs(n)
X = np.empty(n)
for t in range(n-1):
X[t+1] = theta*np.abs(X[t])+d*Z[t+1]
n = len(X)
X = X.reshape((n, 1))
ys = np.linspace(-3,3,200)
k = len(ys)
ys = ys.reshape((1,k))
v = p(X,ys)
kernel = np.mean(v, axis=0)
h = len(kernel)
kernel = kernel.reshape((1,h))
fig, ax = plt.subplots(figsize=(10,7))
ax.plot(ys,kernel, 'b-', lw=2,alpha=0.6, label='look ahead estimate')
plt.show()
The problem is, that through reshaping the two 1-dimensional arrays ys and kernel to a 1xk or 1xh array respectively you get 2-dimensional arrays, where the first dimension is 1. The plot function apparently only iterates through the first dimension, which is why the plot doesn't show anything.
I can think of two easy options to fix that:
Do not reshape the variables kernel and ys:
# ... continuing your code ...
ys = np.linspace(-3,3,200)
k = len(ys)
#ys = ys.reshape((1,k))
v = p(X,ys)
kernel = np.mean(v, axis=0)
h = len(kernel)
#kernel = kernel.reshape((1,h))
fig, ax = plt.subplots(figsize=(10,7))
ax.plot(ys,kernel, 'b-', lw=2,alpha=0.6, label='look ahead estimate')
plt.show()
Call your plot function like this:
ax.plot(ys[0],kernel[0], 'b-', lw=2, alpha=0.6, label='look ahead estimate')
I hope this solves your problem.
To understand why you still have to reshape X:
Let's first understand your function p(x,y) in terms of dimensions:
def p(x,y):
"Stochastic kernel for the TAR model"
"""If x is not reshaped, you substract two one-dimensional arrays from each other,
which have not the same dimensions (dim(x) == 1000, dim(y) == 200 in your case).
This throws an error.
If you reshape X before passing to this function, the y array is substracted
element-wise by each of the values of X, which gives you a matrix with dimension
dim(x) x dim(y).
"""
return norm().pdf((y-theta*np.abs(x))/d)/d
For illustration what happens here dimension-wise:
>>> X = np.array([[1], [2], [3], [4]])
>>> Y = np.array([1, 2, 3])
>>> Y-X
array([[ 0, 1, 2],
[-1, 0, 1],
[-2, -1, 0],
[-3, -2, -1]])
Now we take a look what happens with the matrix returned by p(x,y):
The calculation of the kernel with np.mean(v, axis=0), where v is the returned matrix from p(X,ys), works such, that np.mean iterates over the lines of the matrix v and calculates the mean value of each "line vector" in the matrix. This gives you an one dimensional array (dimension of ys) which you can plot over ys.

Simplify numpy.dot within loop

Is it possible to simplify this:
import numpy as np
a = np.random.random_sample((40, 3))
data_base = np.random.random_sample((20, 3))
mean = np.random.random_sample((40,))
data = []
for s in data_base:
data.append(mean + np.dot(a, s))
data should be of size (20, 40). I was wondering if I could do some broadcasting instead of the loop. I was not able to do it with np.add and some [:, None]. I certainly do not use this correctly.
Your data creates a (20,40) array:
In [385]: len(data)
Out[385]: 20
In [386]: data = np.array(data)
In [387]: data.shape
Out[387]: (20, 40)
The straight forward application of dot produces the same thing:
In [388]: M2=mean+np.dot(data_base, a.T)
In [389]: np.allclose(M2,data)
Out[389]: True
The matmul operator also works with these arrays (no need to expand and squeeze):
M3 = data_base#a.T + mean

Numpy rank 1 arrays

I am Matlab/Octave user. Numpy documentation says the array is much more advisable to use rather than matrix. Is there a convenient way to deal with rank-1 arrays, without reshaping it constantly?
Example:
data = np.loadtxt("ex1data1.txt", usecols=(0,1), delimiter=',',dtype=None)
X = data[:, 0]
y = data[:, 1]
m = len(y)
print X.shape, y.shape
>>> (97L, ) (97L, )
I can't add new column to X using concatenate, vstack, append, except np.c_ which is slower, without reshaping X:
X = np.concatenate((np.ones((m, 1)), X), axis = 1)
>>> ValueError: all the input arrays must have same number of dimensions
X - y, couldn't be done without reshaping y np.reshape(y, (-1, 1))
A simpler equivalent to np.reshape(y, (-1, 1)) is y[:, np.newaxis]. Since np.newaxis is an alias for None, y[:, None] also works. It's also worth mentioning np.expand_dims(y, axis=1).

Categories