if loops and Arrays - arrays

Im trying to plot some data from an experiment but the timer starts a bit before the start of my variable. I have tried to create a new list of times starting from 0 but when I do so my loop generates more values for my array then the length of the original array which makes it impossible to plot.
Aplate = np.loadtxt('Plates Angular poston_2.txt')
t1 = []
for i in Aplate:
t = Aplate[:,0]
for j in t:
if j < 27.4150:
x = j -3.01
t1.append(x)
else:
break
y = Aplate[:,1]
plt.plot(t1, y)
plt.show()

If you are simply accounting for a constant delay in the start of data recording, why not just do
plt.plot( t-delay ,y )
where delay is 3.01? ( see here: https://stackoverflow.com/a/4918586/4916534 )
Also, if you want the columns to be the same length, why not populate y and t in the same loop? You are currently asking python to give you x values for all times < 27.4150, but to give you y values for all times.

Related

How can I merge my data set based on the time in MATLAB?

I want to merge the two data into one. But as they are in two different times that's why I cannot just combine them.
I need to add them by keeping the time as it is.
How can I do this?
data_1_y_axes=[0,1,3,5,4,6,8,9,7]
time_1_x_axes=[.02,0.03,.05,.06,.07,0.08,0.09,.1,.2]
data_2_y_axes=[0,2,4,5,2,7,5,7,5]
time_2_x_axes=[.002,0.004,.006,.009,.02,0.04,0.06,.07,.09]
plot(time_1_x_axes,data_1_y_axes)
hold on
plot(time_2_x_axes,data_2_y_axes)
My expected data will be as follows:
New_data=[ 0, 2,4,5,2+0,1,7,3,5+5,7+4,6,5+8,9,7]
New_time=[.002,.004,.006,.009,.02,.03,.04,.05,.06,.07,.08,.09,.1,.2]
How can I do this?
Here is another way to do it without using a for loop. This will run much faster:
data_1_y_axes=[0,1,3,5,4,6,8,9,7]
time_1_x_axes=[.02,0.03,.05,.06,.07,0.08,0.09,.1,.2]
data_2_y_axes=[0,2,4,5,2,7,5,7,5]
time_2_x_axes=[.002,0.004,.006,.009,.02,0.04,0.06,.07,.09]
[time_merged,i1,i2] = intersect(time_1_x_axes, time_2_x_axes)
data_merged = data_1_y_axes(i1) + data_2_y_axes(i2)
[time1_remaining, ir1] = setdiff(time_1_x_axes, time_merged)
[time2_remaining, ir2] = setdiff(time_2_x_axes, time_merged)
[time_merged, idx] = sort([time_merged time_1_x_axes(ir1) time_2_x_axes(ir2)])
data_merged = [data_merged data_1_y_axes(ir1) data_2_y_axes(ir2)]
data_merged = data_merged(idx)
plot(time_merged,data_merged)
You could combine the x and y axis arrays, then aggregate by x-axis values using
unique to get unique x values and their indices within the y values) and
accumarray to add up all of the y values with a common x axis index
Using your example data, this would look like:
y1 =[0,1,3,5,4,6,8,9,7];
x1 =[.02,0.03,.05,.06,.07,0.08,0.09,.1,.2];
y2 =[0,2,4,5,2,7,5,7,5];
x2 =[.002,0.004,.006,.009,.02,0.04,0.06,.07,.09];
x = [x1, x2]; % Combine x axis data
y = [y1, y2]; % Combine y axis data
[x, ~, idx] = unique( x(:) ); % Get unique x, and their indices
y = accumarray( idx, y ); % Add up y values according to x value index
Aggregating Sample Values With Different Sampling Times
The following approach combines the data into a single vectors, Time_Vector and Data_Vector. Then the unique() function is used to find the unique sample times that exist within Time_Vector. A for-loop is used to evaluate the indices where the same sample time exists by using the find() function. After finding these indices the corresponding values are obtained by using matrix indexing (finds all the values that occur at a given sample time). The aggregate is then taken of this array by using the sum() function.
data_1_y_axes = [0,1,3,5,4,6,8,9,7];
time_1_x_axes = [0.02,0.03,0.05,0.06,0.07,0.08,0.09,0.1,0.2];
data_2_y_axes = [0,2,4,5,2,7,5,7,5];
time_2_x_axes = [0.002,0.004,0.006,0.009,0.02,0.04,0.06,0.07,0.09];
Data_Vector = [data_1_y_axes data_2_y_axes];
Time_Vector = [time_1_x_axes time_2_x_axes];
Unique_Times = unique(Time_Vector);
for Sample_Index = 1: length(Unique_Times)
Time_Value = Unique_Times(Sample_Index);
Indices_With_Matching_Time = find(Time_Vector == Time_Value);
Output_Data(Sample_Index) = sum(Data_Vector(Indices_With_Matching_Time));
end
plot(Unique_Times,Output_Data);
Ran using MATLAB R2019b

Add element to the front of a vector, without knowing if it is a row or column vector?

If i'm adding a newvlaue to a row vector x, it would be
x = [newvlue, x] % use of ,
but if to a column vector x, it would be
x = [newvlue; x] % use of ;
so i have to know in advance if it's a row or column vector in order to perform this front insertion. But i might not always know as x is meant to be a user inputs. So every time i need to perform this row vector or column vector check beforehand. However, let's say I don't really want to care if it's a row or column vector, I just need to add one element at the front of the array. Is there any elegant way to write the code?
You will have to check for the dimension of the input:
x = [1, 2, 3]
% or
x = [1; 2; 3]
new = 0;
% flexible concatenation
y = cat(~(size(x,1) > 1) + 1, new ,x)
Explanation
d = size(x,1) > 1 % check if column (=1) or row vector (>1)
z = ~(d) + 1 % results in either 1 or 2 for column or row vector
% as input for cat
y = cat(z, new ,x) % concatenate in correct dimension
or by using isrow as suggested in ThomasIsCoding's answer, but I guess it almost does the same:
z = isrow(x) + 1;
In any way you should use isvector to check, whether the input is actually a vector and not a matrix. But actually I would recommend to convert any input, row or column vector, into a column vector with
x = x(:)
to allow for consisting coding within your underlying function.
I like one-liners, try this one
a(1:end+1)=[100;a(:)]
works for both row and column matrices.
As #rahnema1 said, just add the new value to the end:
x = flip(x);
x(end+1) = newvalue;
x = flip(x);
Maybe you can define your custom function like below
function y = addhead(x,val)
if isrow(x)
y = horzcat(val,x);
else
y = vertcat(val,x);
end
end
You can use indexing to shift all elements by 1, then insert the new element at the beginning.
x(2:end+1)=x;
x(1)=7;

Filling a row and columns of a ndarray with a loop

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

Plot cell array without loop

I have the following code:
SimRun = 0
Count = 0
for b = 1:0.5:3000
.
.
.
.
Count = Count + 1;
ArrayT(Count) = Time;
ArrayTgo(Count) = tgo;
ArrayY(Count) = Y;
ArrayYD(Count) = YD;
end
SimRun = SimRun + 1;
MAT_ArrayT{SimRun,:} = ArrayT;
MAT_ArrayTgo{SimRun,:} = ArrayTgo;
MAT_ArrayY{SimRun,:} = ArrayY;
MAT_ArrayYD{SimRun,:} = ArrayYD;
As you can see, I have 2 for loops. From the inner loop I receive a vector and from the outer loop I receive in the end a cell array where each cell is a vector.
Now, I had like to plot the cell array to plot basically around 6000 lines and I did it as follows:
for i = 1:SimRun
figure(1)
hold on
plot(MAT_ArrayT{i,:},MAT_ArrayY{i,:})
figure(2)
hold on
plot(MAT_ArrayT{i,:},MAT_ArrayYD{i,:})
end
However this solution takes pretty much time to draw all the lines.
Is there any better solution to store "lines" and plot all of them in one hit at the end?
Thank you.
The plot command takes a matrix and plots each column as a separate line. Assuming you have column vectors in your cell arrays, and they're all the same length, you can do this:
x = [MAT_ArrayT{:}];
y = [MAT_ArrayY{:}];
plot(x,y)
Even better would be to store those vectors in a numeric matrix to start with, so you don't need to make the extra copy.

Having trouble randomly generating numbers in multidimensional arrays

I'm trying to generate coordinates in a mulidimensional array.
the range for each digit in the coords is -1 to 1. <=> seems like the way to go comparing two random numbers. I'm having trouble because randomizing it takes forever, coords duplicate and sometimes don't fill all the way through. I've tried uniq! which only causes the initialization to run forever while it tries to come up with the different iterations.
the coords look something like this. (-1, 0, 1, 0, 0)
5 digits give position. I could write them out but I'd like to generate the coords each time the program is initiated. The coords would then be assigned to a hash tied to a key. 1 - 242.
I could really use some advice.
edited to add code. It does start to iterate but it doesn't fill out properly. Short of just writing out an array with all possible combos and randomizing before merging it with the key. I can't figure out how.
room_range = (1..241)
room_num = [*room_range]
p room_num
$rand_loc_cords = []
def Randy(x)
srand(x)
y = (rand(100) + 1) * 1500
z = (rand(200) + 1) * 1000
return z <=> y
end
def rand_loc
until $rand_loc_cords.length == 243 do
x = Time.new.to_i
$rand_loc_cords.push([Randy(x), Randy(x), Randy(x), Randy(x), Randy(x)])
$rand_loc_cords.uniq!
p $rand_loc_cords
end
#p $rand_loc_cords
end
rand_loc
You are trying to get all possible permutations of -1, 0 and 1 with a length of 5 by sheer luck, which can take forever. There are 243 of them (3**5) indeed:
coords = [-1,0,1].repeated_permutation(5).to_a
Shuffle the array if the order should be randomized.

Resources