Hi I'm trying to write simple for loop with if loop to only calculate the mean of an array column wise (so i end up with just one row array as a mean), except column number 1051 and 1552. Here the input array has 2151 columns and 12 rows. The result in mean array should be 2149 columns and 12 rows. Here is the code I wrote
function specmeanex, a
m=make_array(2151,1)
for i=0,2150,1 do begin
if (i ne 1051) or (i ne 1552) then begin
m[i,0]=mean(a[i,*])
endif
endfor
plot,m
return,m
end
How can i either assign the empty spaces to 0 using an else? Can anyone please help me out here since I'm quite new to IDL
You could just add an else clause like this:
if (i ne 1051) or (i ne 1552) then begin
m[i,0]=mean(a[i,*])
endif else m[i,0] = 0.0
But, I recommend changing the code a bit to remove the for loop. IDL can be very efficient in vectorized operations that operate on arrays all in one statement, but slow when looping over elements of an array. Here, you are looping over the columns, which is not so bad, but could be made more IDL-like.
Try this code:
function mg_column_mean_exclude, a, exclude_columns
compile_opt strictarr
m = mean(a, dimension=2)
m[exclude_columns] = 0.0
return, m
end
Then you can call it similar to your previous routine, except you would pass in the excluded columns too:
m = mg_column_mean(a, [1051, 1552])
Related
I'm starting with Python and I have a basic question with "for" loop
I have two array which contains a values of a same variables:
A = data_lac[:,0]
In the first array, I have values of area and in the second on, values of mean depth.
I would like to find a way to automatize my calculation with different value of a parameter. The equation is the following one:
g= (np.sqrt(A/pi))/n
Here I can calculte my "g" for each row. Now I want to have a loop with differents values of "n". I did this:
i=0
while i <= len(A)-1:
for n in range(2,6):
g[i] = (np.sqrt(A[i]/pi))/n
i += 1
break
In this case, I just have one column with the calculation for n = 2 but not the following one. I tried to add a second dimension to my array but I have an error message saying that I have too many indices for array.
In other, I would like this array:
g[len(A),5]
g has 5 columns each one calculating with a different "n"
Any tips would be very helpful,
Thanks
Update of the code:
data_lac=np.zeros((106,7))
data_lac[:,0:2]=np.loadtxt("/home...", delimiter=';', skiprows=1, usecols=(0,1))
data_lac[:,1]=data_lac[:,1]*0.001
#Initialisation
A = data_lac[:,0]
#example for A with 4 elements
A=[2.1, 32.0, 4.6, 25]
g = np.zeros((len(A),))
I believe you share the indexes within both loops. You were increasing the i (index for the upper while loop) inside the inner for loop (which index with n).
I guess you have A (1 dim array) and you want to produce G (2 dim array) with size of (Len(A, 5))
I am not sure I'm fully understand your require output but I believe you want something like:
i=0
while i <= len(A)-1:
for n in range(2,6):
g[i][n-2] = (np.sqrt(A[i]/pi))/n # n-2 is to get first index as 0 and last as 4
i += 1 # notice the increace of the i is for the upper while loop
break
Important - remember that in python indentation means a lot -> so make sure the i +=1 is under the while scope and not indent to be inside the for loop
Notice - G definition should be as:
g = np.zeros((len(A),4), dtype=float)
The way you define it (without the 4) cause it to be 1 dim array and not 2-dim
I have a for loop and each value a{i} b{i} c{i} is equal each time with a specific number. So I was wondering how can I put all those value in an array through loop. The way that I am using I mean this one [a{i};b{i};c{i}] it seems that it doesn't work! If I keep 2 out of three values is working but I want the data from all of the values (a b c)
You can see the (pseudo)code below:
for i=1:number of cells
Cell{i}.Tri=[a{i};b{i};c{i}]
end
cell2mat is what you need:
a = num2cell(rand(1,10));
b = num2cell(rand(1,10));
c = num2cell(rand(1,10));
abc = cell2mat([a;b;c]);
This can be done without a for loop by using cellfun combined with the cat function. EDIT: As noted in the comments, cellfun is itself a loop.
% Create all variables
a{1}=rand(10);
a=repmat(a,10,1);
b=a;
c=a;
% Add a cell array of equal size to a. The contents of each cell are the dimension along which to concatenate.
catarg=num2cell(ones(size(a)))
% Do the concatenation
d=cellfun(#cat,catarg,a,b,c,'UniformOutput',false);
I've just started using for loops in matlab in programming class and the basic stuff is doing me fine, However I've been asked to "Use loops to create a 3 x 5 matrix in which the value of each element is its row number to the power of its column number divided by the sum of its row number and column number for example the value of element (2,3) is (2^3 / 2+3) = 1.6
So what sort of looping do I need to use to enable me to start new lines to form a matrix?
Since you need to know the row and column numbers (and only because you have to use loops), for-loops are a natural choice. This is because a for-loop will automatically keep track of your row and column number for you if you set it up right. More specifically, you want a nested for loop, i.e. one for loop within another. The outer loop might loop through the rows and the inner loop through the columns for example.
As for starting new lines in a matrix, this is extremely bad practice to do in a loop. You should rather pre-allocate your matrix. This will have a major performance impact on your code. Pre-allocation is most commonly done using the zeros function.
e.g.
num_rows = 3;
num_cols = 5;
M = zeros(num_rows,num_cols); %// Preallocation of memory so you don't grow your matrix in your loop
for row = 1:num_rows
for col = 1:num_cols
M(row,col) = (row^col)/(row+col);
end
end
But the most efficient way to do it is probably not to use loops at all but do it in one shot using ndgrid:
[R, C] = ndgrid(1:num_rows, 1:num_cols);
M = (R.^C)./(R+C);
The command bsxfun is very helpful for such problems. It will do all the looping and preallocation for you.
eg:
bsxfun(#(x,y) x.^y./(x+y), (1:3)', 1:5)
I have a vector,"a", and a filter,"b".Both of those vectors contain only 0 or 1.
I would like to transform "a" such that any sequence of 1 only starts when b is at 1.
I have illustrated this using a loop but, as my vectors are huge, it is extremely inefficient.
The result I would like is stored in "r".
a=[0;0;1;1;1;1;1;1;0;0;1;1;0;0;1;1;1;1;1];
b=[0;0;0;0;1;0;1;0;0;1;0;1;0;1;1;0;0;0;0];
r=[0;0;0;0;1;1;1;1;0;0;0;1;0;0;1;1;1;1;1];
for i=2:length(a)
if a(i)==1 &&a(i-1)==0 && b(i)==0
a(i)=a(i-1);
end
end
assert(sum(a==r)==length(a))
Here's a two-liner:
r = a;
r([false; diff(a)>0 & b(2:end)==0]) = 0;
Please note that you need to adapt the code for row vectors (this works for column vectors).
In a program I'm writing, I've created an allocated, final product array AFT(n,92). In my output I would like present each row as its own table, 5 columns wide.
So in this case, it would be n individual tables of 19 rows X 5 columns with only 2 values on the final row. I attempted doing this as a do loop as shown in the code snip below, but the output comes out as just one long column. I'm not sure where to go from here.
DO i=1,n
WRITE(4,800) t(i), ' HHMM LDT' !Writes the table header using an array which holds the corresponding time value
800 FORMAT(14, A9)
DO j=1,92
WRITE(4,900) AFT(i,j)
900 FORMAT(5ES23.14)
END DO
END DO
I believe this is happening because the write command is performed for each j individually due to the use of a loop, but my inexperience with FORTRAN is leading me to a blank when I try to come up another approach.
Yes, each write statement produces one line of text output. If you want multiple items to be included in the same output record, you have to include them in the write statement. If you want to include portions of an array, you can use techniques such as:
do i=1, N
write (*, *) (array (i,j), j=1, 5)
end do
or
do i=1, N
write (*, *) array (i, 1:5)
end do
The first is using implied do loops, the second array sections.