Saving vectors into a matrix matlab - arrays

I have a bunch of arrays that I have generated from a loop
Peaks [1, 2, 3, 4, 5]
Latency [23,24,25,26,27] etc.
I want to put all of those in a matrix that will look like that:
Peaks Latency
1 23
2 24
3 25
4 26
5 27
Then I'll want to save this as a text file.
It seems like it would be fairly simple but can't seem to find anything that closely speaks to me right now.

Concatentate:
>> Peaks = [1 2 3 4 5];
>> Latency = [23 24 25 26 27];
>> T = [Peaks(:) Latency(:)]
T =
1 23
2 24
3 25
4 26
5 27
Write:
fileName = 'PeaksLatency.txt';
hdr = {'Peaks','Latency'}
txt = sprintf('%s\t',hdr{:}); txt(end) = [];
dlmwrite(fileName,txt,''); % write header
dlmwrite(fileName,T,'-append','delimiter','\t'); % append data

Here is the code
Peaks = [1, 2, 3, 4, 5].';
Latency = [23,24,25,26,27].';
T = table(Peaks, Latency);
writetable(T,'table.txt', 'Delimiter', '\t');
Note that you need to make Peaks and Latency into column vectors (use .' operator).
Ref: http://www.mathworks.com/help/matlab/ref/writetable.html

Related

MATLAB: extract values from 3d matrix at given row and column indcies using sub2ind 3d

I have 3d matrix A that has my data. At multiple locations defined by row and column indcies as shown by matrix row_col_idx I want to extract all data along the third dimension as shown below:
A = cat(3,[1:3;4:6], [7:9;10:12],[13:15;16:18],[19:21;22:24]) %matrix(2,3,4)
row_col_idx=[1 1;1 2; 2 3];
idx = sub2ind(size(A(:,:,1)), row_col_idx(:,1),row_col_idx(:,2));
out=nan(size(A,3),size(row_col_idx,1));
for k=1:size(A,3)
temp=A(:,:,k);
out(k,:)=temp(idx);
end
out
The output of this code is as follows:
A(:,:,1) =
1 2 3
4 5 6
A(:,:,2) =
7 8 9
10 11 12
A(:,:,3) =
13 14 15
16 17 18
A(:,:,4) =
19 20 21
22 23 24
out =
1 2 6
7 8 12
13 14 18
19 20 24
The output is as expected. However, the actual A and row_col_idx are huge, so this code is computationally expensive. Is there away to vertorize this code to avoid the loop and the temp matrix?
This can be vectorized using linear indexing and implicit expansion:
out = A( row_col_idx(:,1) + ...
(row_col_idx(:,2)-1)*size(A,1) + ...
(0:size(A,1)*size(A,2):numel(A)-1) ).';
The above builds an indexing matrix as large as the output. If this is unacceptable due to memory limiations, it can be avoided by reshaping A:
sz = size(A); % store size A
A = reshape(A, [], sz(3)); % collapse first two dimensions
out = A(row_col_idx(:,1) + (row_col_idx(:,2)-1)*sz(1),:).'; % linear indexing along
% first two dims of A
A = reshape(A, sz); % reshape back A, if needed
A more efficient method is using the entries of the row_col_idx vector for selecting the elements from A. I have compared the two methods for a large matrix, and as you can see the calculation is much faster.
For the A given in the question, it gives the same output
A = rand([2,3,10000000]);
row_col_idx=[1 1;1 2; 2 3];
idx = sub2ind(size(A(:,:,1)), row_col_idx(:,1),row_col_idx(:,2));
out=nan(size(A,3),size(row_col_idx,1));
tic;
for k=1:size(A,3)
temp=A(:,:,k);
out(k,:)=temp(idx);
end
time1 = toc;
%% More efficient method:
out2 = nan(size(A,3),size(row_col_idx,1));
tic;
for jj = 1:size(row_col_idx,1)
out2(:,jj) = [A(row_col_idx(jj,1),row_col_idx(jj,2),:)];
end
time2 = toc;
fprintf('Time calculation 1: %d\n',time1);
fprintf('Time calculation 2: %d\n',time2);
Gives as output:
Time calculation 1: 1.954714e+01
Time calculation 2: 2.998120e-01

How do I retrieve an array of arrays of arrays in Julia?

I am new in Julia, so don't judge me please (ha ha)
This is my situation: I needed to save several 2x2x2 matrices whose elements were vectors of 4 elements, but now when I try to retrieve them from a file, I can't !!!
This is what I did:
To create these matrices I made this function
function InitialConf(L_=2,S_=2,T_=2,Dim_=4)
Conf_=Array{Array{Float64,1}}(L_,S_,T_)
for i_ = 1:L_, j_=1:S_,k_=1:T_
Conf_[i_,j_,k_]=RanUniVec(Dim_)
end
return Conf_
end
Where RanUniVec(Dim_) is the function that creates these vectors of 4 dimentions with special characteristics that are not important for this discussion:
function RanUniVec(Dim_)
vector_=Array{Float64}(Dim_)
while true
for i_ in 1:Dim_
vector_[i_]=UniformRand(-1,1)
end
if norm(vector_)<1 && norm(vector_)>0.5
break
end
end
vector_=normalize(vector_) # 2-norm
return vector_
end
function UniformRand(a_,b_)
rand_=(b_-a_)*rand()+a_
return rand_
end
I needed two of these matrices (for example) so I did the next:
States=[]
Conf1=InitialConf()
Conf2=InitialConf()
push!(States,Conf1)
push!(States,Conf2)
f=open("Info.txt","w") do f
write(f,"$States")
end
This made the Info.txt file where is my information, but when I try to get the States array again from this file, Julia tells me that it can't
f=readlines("Info.txt")
States=parse(f)
ERROR: MethodError: no method matching parse(::Array{String,1})
Closest candidates are:
parse(::Type{IPv4}, ::AbstractString) at socket.jl:167
parse(::Type{IPv6}, ::AbstractString) at socket.jl:218
parse(::Type{DateTime}, ::AbstractString, ::DateFormat{Symbol("yyyy-mm-dd\\THH:MM:SS.s"),Tuple{Base.Dates.DatePart{'y'},Base.Dates.Delim{Char,1},Base.Dates.DatePart{'m'},Base.Dates.Delim{Char,1},Base.Dates.DatePart{'d'},Base.Dates.Delim{Char,1},Base.Dates.DatePart{'H'},Base.Dates.Delim{Char,1},Base.Dates.DatePart{'M'},Base.Dates.Delim{Char,1},Base.Dates.DatePart{'S'},Base.Dates.Delim{Char,1},Base.Dates.DatePart{'s'}}}) at dates/parse.jl:202
...
Do you know how I can get again my State array?
In general you should use Colin's recommendation from the comment in the long run. Here is what you can do if you actually have those text files already generated. I will use a smaller example.
Assume your original array is consisting of two 2x2x2 arrays. Here is an example I will use:
julia> z
2-element Array{Array{Int64,3},1}:
[1 2; 3 4]
[10 20; 30 40]
[1 2; 3 4]
[10 20; 30 40]
julia> z[1]
2×2×2 Array{Int64,3}:
[:, :, 1] =
1 2
3 4
[:, :, 2] =
10 20
30 40
julia> z[2]
2×2×2 Array{Int64,3}:
[:, :, 1] =
1 2
3 4
[:, :, 2] =
10 20
30 40
Now it will get saved to a file as the following string:
julia> repr(z)
"Array{Int64,3}[[1 2; 3 4]\n\n[10 20; 30 40], [1 2; 3 4]\n\n[10 20; 30 40]]"
And parsing this string will clearly fail. What you have to do is to edit your files to add cat method invocation on each entry of a big array and pass dimension 3 as the one on which you want to cat them.
This means that from the original contents of the save file:
Array{Int64,3}[[1 2; 3 4]
[10 20; 30 40], [1 2; 3 4]
[10 20; 30 40]]
You have to make this file contain:
Array{Int64,3}[cat(3, [1 2; 3 4], [10 20; 30 40]),
cat(3, [1 2; 3 4], [10 20; 30 40])]
Those changes can be done either by hand or you could write a program to perform the transformation (you have to replace , by ), cat(3,; \n\n by ,; make sure that first cat and last ) are added as they will not be caught by the first two rules).
Now if you read it in it as a string you can evaluate result of parsing it:
julia> s = """Array{Int64,3}[cat(3, [1 2; 3 4], [10 20; 30 40]),
cat(3, [1 2; 3 4], [10 20; 30 40])]"""
"Array{Int64,3}[cat(3, [1 2; 3 4], [10 20; 30 40]),\ncat(3, [1 2; 3 4], [10 20; 30 40])]"
julia> eval(parse(s))[2]
2×2×2 Array{Int64,3}:
[:, :, 1] =
1 2
3 4
[:, :, 2] =
10 20
30 40
Note, however, that all this is not recommended - it is better to use the packages that Colin recommended to do this.
Not directly an answer to your specific question, but a general recommendation for future development. To save data to disk, and reload later, give preference to formats such as JLD2.jl.
You save with
#save "filename.jld2" ARRAY
and load with
#load "filename.jld2" ARRAY
without having to figure out what was the format you chose in the past. Saves a lot of headache with complex data structures.

Delete values between specific ranges of indices in an array

I have an array :
Z = [1 24 3 4 52 66 77 8 21 100 101 120 155];
I have another array:
deletevaluesatindex=[1 3; 6 7;10 12]
I want to delete the values in array Z at indices (1 to 3, 6 to 7, 10 to 12) represented in the array deletevaluesatindex
So the result of Z is:
Z=[4 52 8 21 155];
I tried to use the expression below, but it does not work:
X([deletevaluesatindex])=[]
Another solution using bsxfun and cumsum:
%// create index matrix
idx = bsxfun(#plus , deletevaluesatindex.', [0; 1])
%// create mask
mask = zeros(numel(Z),1);
mask(idx(:)) = (-1).^(0:numel(idx)-1)
%// extract unmasked elements
out = Z(~cumsum(mask))
out = 4 52 8 21 155
This will do it:
rdvi= size(deletevaluesatindex,1); %finding rows of 'deletevaluesatindex'
temp = cell(1,rdvi); %Pre-allocation
for i=1:rdvi
%making a cell array of elements to be removed
temp(i)={deletevaluesatindex(i,1):deletevaluesatindex(i,2)};
end
temp = cell2mat(temp); %Now temp array contains the elements to be removed
Z(temp)=[] % Removing the elements
If you control how deletevaluesatindex is generated, you can instead directly generate the ranges using MATLAB's colon operator and concatenate them together using
deletevaluesatindex=[1:3 6:7 10:12]
then use the expression you suggested
Z([deletevaluesatindex])=[]
If you have to use deletevaluesatindex as it is given, you can generate the concatenated range using a loop or something like this
lo = deletevaluseatindex(:,1)
up = deletevaluseatindex(:,2)
x = cumsum(accumarray(cumsum([1;up(:)-lo(:)+1]),[lo(:);0]-[0;up(:)]-1)+1);
deleteat = x(1:end-1)
Edit: as in comments noted this solution only works in GNU Octave
with bsxfun this is possible:
Z=[1 24 3 4 52 66 77 8 21 100 101 120 155];
deletevaluesatindex = [1 3; 6 7;10 12];
idx = 1:size(deletevaluesatindex ,1);
idx_rm=bsxfun(#(A,B) (A(B):deletevaluesatindex (B,2))',deletevaluesatindex (:,1),idx);
Z(idx_rm(idx_rm ~= 0))=[]

Storing blocks of vector data into an array in Matlab

I have an array in Matlab
A = [1 2 3 4 5 6 7 8 9;
67 67 67 86 86 86 86 67 67]';
where every point in the first row of A corresponds to a "code" either 67 or 86. I am trying to extract these blocks of "67s" and "86s" such that every time a block starts the corresponding elements are put into the 3rd dimension of a different array called X, where the .
So for e.g. in A I have 3 different blocks, so I would like to end up with an array X of size 1x9x3. And for e.g. the first 67 block I would like to have X
X(1,:,1) = [1 2 3];
I understand that I would "fill up" this vector X using a for loop
for i=1:size(A,2)
for j=1:size(A,2) %actually j should be up till the number of blocks present
X(1,i,j) = A(1,i)
end
end
But this isn't correct or complete of course because firstly I'm unsure how to separate out the "blocks" and how to correctly "fill in" the j's in X(1,i,j). Secondly how can I get the code to recognise how many blocks there are?
Can anyone help?
Thanks
One possible approach, based on this answer:
>> B = accumarray([0; cumsum(diff(A(:,2)) ~= 0)] + 1, A(:,1), [], #(x) {x}, [])
Now you have this:
>> B{1}
ans =
1
2
3
>> B{2}
ans =
4
5
6
7
>> B{3}
ans =
8
9

Partial sum of divisions of a vector

If there is a vector like this,
T = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
(the size of vector T can be flexible)
How can I get a array of 'sum of divisions'?
For example,
fn(T, 5) = [ (1+2+3+4+5) , (6+7+8+9+10), (11+12+13+14+15) , 16]
One option, which doesn't require the padding of zeros on the original array, is the use of accumarray and ceil:
div = 5;
out = accumarray(ceil((1:numel(T))/div).',T(:))
Another option using cumsum and diff instead:
div = 5;
T(ceil(numel(T)/div)*div) = 0;
cs = cumsum(T)
out = diff( [0 cs(div:div:end) ] )
Edit: once the padding is done, cumsum and diff are a little overkill and one should proceed as in Bentoy's answer.
Another way, close to the 2nd option of thewaywewalk:
div = 5;
T(ceil(numel(T)/div)*div) = 0;
out = sum(reshape(T,div,[])).'; % transpose if you really want a column vector
Also, one one-liner solution (I prefer this one):
out = blockproc(T,[1 5], #(blk) sum(blk.data), 'PadPartialBlocks',true);
Don't forget to set the parameter 'PadPartialBlocks', this is the key of avoiding explicit padding.
There is an in-built function vec2mat in Communications System Toolbox to convert a vector into a 2D matrix that cuts off after every N elements and puts into separate rows, padding the leftover places at the end with zeros to maintain 2D size . So, after using vec2mat, summing all the rows would be enough to give you the desired output. Here's the implementation -
sum(vec2mat(T,5),2)
Sample run -
>> T = 1:16;
>> vec2mat(T,5)
ans =
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 0 0 0 0
>> sum(vec2mat(T,5),2)
ans =
15
40
65
16

Resources