Matlab Concatenating Row Vectors With A For Loop - python

Here is what I did:
w = zeros(1,28);
e = zeros(1,63) + 1;
r = zeros(1,90) + 2;
t = zeros(1,100) + 3;
y = zeros(1,90) + 4;
u = zeros(1,63) + 5;
i = zeros(1,28) + 6;
qa = horzcat(w,e,r,t,y,u,i);
hist(qa,25,0.5)
h = findobj(gca,'Type','patch');
set(h,'FaceColor',[.955 0 0],'EdgeColor','w');
I would like to achieve the effect, but it in a more succinct way. This is my attempt:
v= zeros(1,28);
for i=2:8
v(i) = horzcat(v(i-1) + (i-1));
end
And the error I receive is "Cell contents assignment to a non-cell array object."
Also, would anyone know what the python equivalent would be, if it is not too much to ask?

You can also achieve this without a for loop, albeit somewhat less intiutive. But hey, it's without loops! Besides, it gives you freedom to pick a different set of values.
v=[0;1;2;3;4;5;6]; %values
r=[28 63 90 100 90 63 28]; %number of repeats
qa=zeros(sum(r),1);
qa(cumsum([1 r(1:end-1)]))=1;
qa=v(cumsum(qa));

You don't need a cell array to concatenate vectors for which one of the dimensions always remain the same (for example, row or columns, in your case, row).
You can define the sizes in a separate array and then use for loop as follows.
szArray=[28 63 90 100 90 63 28];
qa=[];
for i=0:length(szArray)-1
%multiplying by i replicates the addition of a scalar you have done.
qa=[qa i*ones(1,szArray(i+1)];
end
This is still hardcoding. It will only apply to the exact problem you have mentioned above.

Related

Create arrays of fixed size within a while loop in python

I am trying to create arrays of fixed size within a while loop. Since I do not know how many arrays I have to create, I am using a loop to initiate them within a while loop. The problem I am facing is, with the array declaration.I would like the name of each array to end with the index of the while loop, so it will be later useful for my calculations. I do not expect to find a easy way out, however it would be great if someone can point me in the right direction
I tried using arrayname + str(i). This returns the error 'Can't assign to operator'.
#parse through the Load vector sheet to load the values of the stress vector into the dataframe
Loadvector = x2.parse('Load_vector')
Lvec_rows = len(Loadvector.index)
Lvec_cols = len(Loadvector.columns)
i = 0
while i < Lvec_cols:
y_values + str(i) = np.zeros(Lvec_rows)
i = i +1
I expect arrays with names arrayname1, arrayname2 ... to be created.
I think the title is somewhat misleading.
An easy way to do this would be using a dictionary:
dict_of_array = {}
i = 0
while i < Lvec_cols:
dict_of_array[y_values + str(i)] = np.zeros(Lvec_rows)
i = i +1
and you can access arrayname1 by dict_of_array[arrayname1].
If you want to create a batch of arrays, try:
i = 0
while i < Lvec_cols:
exec('{}{} = np.zeros(Lvec_rows)'.format(y_values, i))
i = i +1

What is the equivalent way of doing this type of pythonic vectorized assignment in MATLAB?

I'm trying to translate this line of code from Python to MATLAB:
new_img[M[0, :] - corners[0][0], M[1, :] - corners[1][0], :] = img[T[0, :], T[1, :], :]
So, naturally, I wrote something like this:
new_img(M(1,:)-corners(2,1),M(2,:)-corners(2,2),:) = img(T(1,:),T(2,:),:);
But it gives me the following error when it reaches that line:
Requested 106275x106275x3 (252.4GB) array exceeds maximum array size
preference. Creation of arrays greater than this limit may take a long
time and cause MATLAB to become unresponsive. See array size limit or
preference panel for more information.
This has made me believe that it is not assigning things correctly. Img is at most a 1000 × 1500 RGB image. The same code works in less than 5 seconds in Python. How can I do vector assignment like the code in the first line in MATLAB?
By the way, I didn't paste all lines of my code for this post not to get too long. If I need to add anything else, please let me know.
Edit:
Here's an explanation of what I want my code to do (basically, this is what the Python code does):
Consider this line of code. It's not a real MATLAB code, I'm just trying to explain what I want to do:
A([2 3 5], [1 3 5]) = B([1 2 3], [2 4 6])
It is interpreted like this:
A(2,1) = B(1,2)
A(3,1) = B(2,2)
A(5,1) = B(3,2)
A(2,3) = B(1,4)
A(3,3) = B(2,4)
A(5,3) = B(3,4)
...
...
...
Instead, I want it to be interpreted like this:
A(2,1) = B(1,2)
A(3,3) = B(2,4)
A(5,5) = B(3,6)
When you do A[vector1, vector2] in Python, you index the set:
A[vector1[0], vector2[0]]
A[vector1[1], vector2[1]]
A[vector1[2], vector2[2]]
A[vector1[3], vector2[3]]
...
In MATLAB, the similar-looking A(vector1, vector2) instead indexes the set:
A(vector1(1), vector2(1))
A(vector1(1), vector2(2))
A(vector1(1), vector2(3))
A(vector1(1), vector2(4))
...
A(vector1(2), vector2(1))
A(vector1(2), vector2(2))
A(vector1(2), vector2(3))
A(vector1(2), vector2(4))
...
That is, you get each combination of indices. You should think of it as a sub-array composed of the rows and columns specified in the two vectors.
To accomplish the same as the Python code, you need to use linear indexing:
index = sub2ind(size(A), vector1, vector2);
A(index)
Thus, your MATLAB code should do:
index1 = sub2ind(size(new_img), M(1,:)-corners(2,1), M(2,:)-corners(2,2));
index2 = sub2ind(size(img), T(1,:), T(2,:));
% these indices are for first 2 dims only, need to index in 3rd dim also:
offset1 = size(new_img,1) * size(new_img,2);
offset2 = size(img,1) * size(img,2);
index1 = index1.' + offset1 * (0:size(new_img,3)-1);
index2 = index2.' + offset2 * (0:size(new_img,3)-1);
new_img(index1) = img(index2);
What the middle block does here is add linear indexes for the same elements along the 3rd dimension. If ii is the linear index to an element in the first channel, then ii + offset1 is an index to the same element in the second channel, and ii + 2*offset1 is an index to the same element in the third channel, etc. So here we're generating indices to all those matrix elements. The + operation is doing implicit singleton expansion (what they call "broadcasting" in Python). If you have an older version of MATLAB this will fail, you need to replace that A+B with bsxfun(#plus,A,B).

Python increment loop to add filter parameters to dataframe

I created a dictionary with a set of functions. Then, I created a while loop that attempts to use those functions. But part of the loop doesn't call the functions the way I want it to. Here's the code:
while bool(str(w).endswith(' 2')) != True:
a = re.search('[0-9]{1,2}$', str(w))
w = w & int(a.group())-1
result = df[f[w]]
The third line, w = w & int(a.group())-1, doesn't function the way I want when I test it outside of this loop. I try setting w = 34, and then testing what results when I do 34 & int(a.group())-1. Instead of giving me 34 & 33, I get 32. Is there any way to create an increment that adds parameters to the result, instead of creating some integer that doesn't even seem to be derived logically? I would like it to start with 34, and add an integer that is one less for every go around the loop (34, 34 & 33, 34 & 33 & 32, etc.). Thanks in advance!
34 & 33 is 32. & is the bitwise and operator.
Saying you want "34 & 33" suggests that you want a string as a result, but that seems to conflict w/ the use of str(w) throughout your code. Or maybe you are just unclear about what & does, and really want some different operation.
Okay, I figured it out. I needed q = f[w] and then q = q & f[w-n], where f[w] defines parameters to filter a dataframe (df) based on a column, and f[w-n] defines a different parameter for filtering based on the next adjacent column. So, the progression should be f[w], f[w] & f[w-n], f[w] & f[w-n] & f[w-n], etc., instead of 34, 34 & 33, 34 & 33 & 32, etc. while n <= w.
So that would look like this:
w = 34
n = 1
q = f[w]
while n <= w:
q = q & f[w-n]
result = df[q]
n = n+1
And, there would be conditions later on to decide whether or not enough parameters were used. In my usage, I'm not looking for a result before the while loop after q is initially defined because that result would have already been found in a different portion of the program. (In case this helps anyone else.)
Scott Hunter thanks for the tip on the & operator.

IndexError: invalid index to scalar variable for double 'for' statement

My purpose is to calculate the list of certain variable repetitively using for statement inside of for statement.
My code is as follows.
for b in range(0,1487):
c = 18000*b
alpha = np.arctan(np.mean(v[c:c+18000])/np.mean(u[c:c+18000]))
beta = np.arctan(np.mean(w[c:c+18000])/np.mean(u[c:c+18000]))
R01 = R01.reshape((3,3))
for c1 in range(c,c+18000):
windvector = np.array([u[c1],v[c1],w[c1]])
WV = windvector.reshape((3,1))
m = np.dot(R01,WV)
m = m.reshape((1,3))
m = list(m)
M = M + m
for c2 in range(0,18000):
u = M[c2][0]
A = A + [u]
m1 = np.mean(A[0:3000])
m2 = np.mean(A[3000:3000*2])
m3 = np.mean(A[3000*2:3000*3])
m4 = np.mean(A[3000*3:3000*4])
m5 = np.mean(A[3000*4:3000*5])
m6 = np.mean(A[3000*5:3000*6])
M = [m1,m2,m3,m4,m5,m6]
s1 = np.std(A[0:3000])
s2 = np.std(A[3000:3000*2])
s3 = np.std(A[3000*2:3000*3])
s4 = np.std(A[3000*3:3000*4])
s5 = np.std(A[3000*4:3000*5])
s6 = np.std(A[3000*5:3000*6])
S = [s1,s2,s3,s4,s5,s6]
RN = fabs((np.mean(S)-np.std(A))/np.std(A))
RNT = RNT + [RN]
As shown in the code, I would like to get 1487 RN values repetitively, but when I ran this code,
this stopped just after 1 rotation among expected 1487, showing the error message of "File "RN_stationarity.py", line 25, in alpha = np.arctan(np.mean(v[c:c+18000])/np.mean(u[c:c+18000])) IndexError: invalid index to scalar variable."
I am not sure why I got this kind of error. I tried few solution in stackoverflow, but it didn't work.
Would you please give some idea or help?
It will be really appreciated.
Thank you,
Isaac
Your problem is that you use the name u for two completely different values. At the start of this loop, it's a nice big array, but in the middle of the loop you reassign it to a scalar, hence the IndexError when you try to index it the next time through the loop.
From the comments:
u should have total 1487*18000 numbers which I already checked
So, that's how I know it starts off valid.
But then in the middle of the loop:
for c2 in range(0,18000):
u = M[c2][0]
A = A + [u]
From other comments, M is a 2D array. So, after this loop, u is a 0D array (that is, a scalar).
The solution is to just not use the name u for two unrelated things. Rename one of them to something else.
More generally, the solution is to not use meaningless one-letter variable names, because when you do that, it's very hard to avoid accidentally reusing one, and also hard to tell when you've done so.

Is vectorizing this triple for loop in Python / Numpy possible?

I am trying to speed up my code which currently takes a little over an hour to run in Python / Numpy. The majority of computation time occurs in the function pasted below.
I'm trying to vectorize Z, but I'm finding it rather difficult for a triple for loop. Could I possible implement the numpy.diff function somewhere? Take a look:
def MyFESolver(KK,D,r,Z):
global tdim
global xdim
global q1
global q2
for k in range(1,tdim):
for i in range(1,xdim-1):
for j in range (1,xdim-1):
Z[k,i,j]=Z[k-1,i,j]+r*q1*Z[k-1,i,j]*(KK-Z[k-1,i,j])+D*q2*(Z[k-1,i-1,j]-4*Z[k-1,i,j]+Z[k-1,i+1,j]+Z[k-1,i,j-1]+Z[k-1,i,j+1])
return Z
tdim = 75 xdim = 25
I agree, it's tricky because the BCs on all four sides, ruin the simple structure of the Stiffness matrix. You can get rid of the space loops as such:
from pylab import *
from scipy.sparse.lil import lil_matrix
tdim = 3; xdim = 4; r = 1.0; q1, q2 = .05, .05; KK= 1.0; D = .5 #random values
Z = ones((tdim, xdim, xdim))
#Iterate in time
for k in range(1,tdim):
Z_prev = Z[k-1,:,:] #may need to flatten
Z_up = Z_prev[1:-1,2:]
Z_down = Z_prev[1:-1,:-2]
Z_left = Z_prev[:-2,1:-1]
Z_right = Z_prev[2:,1:-1]
centre_term = (q1*r*(Z_prev[1:-1,1:-1] + KK) - 4*D*q2)* Z_prev[1:-1,1:-1]
Z[k,1:-1,1:-1]= Z_prev[1:-1,1:-1]+ centre_term + q2*(Z_up+Z_left+Z_right+Z_down)
But I don't think you can get rid of the time loop...
I think the expression:
Z_up = Z_prev[1:-1,2:]
makes a copy in numpy, whereas what you want is a view - if you can figure out how to do this - it should be even faster (how much?)
Finally, I agree with the rest of the answerers - from experience, this kind of loops are better done in C and then wrapped into numpy. But the above should be faster than the original...
This looks like an ideal case for Cython. I'd suggest writing that function in Cython, it'll probably be hundreds of times faster.

Categories

Resources