MATLAB - Counting the # of rows that are only numbered with multiples of 5 - matlab

I am currently doing a project that involves MATLAB and I just can't seem to figure out a way to solve this problem. I have a data set that looks like this:
262 23 34
262 23 34
262 23 35
262 23 38
262 23 38
262 23 39
262 23 40
262 23 41
262 23 42
262 23 43
262 23 45
262 23 46
262 23 47
262 23 48
262 23 50
262 23 50
262 23 51
262 23 52
262 23 55
262 23 57
262 23 58
263 0 0
263 0 2
263 0 4
263 0 7
263 0 10
263 0 15
263 0 25
263 0 29
263 0 32
263 0 39
263 1 1
272 23 28
272 23 30
272 23 56
273 0 1
273 0 2
273 0 3
273 0 3
273 0 4
273 0 4
273 0 5
273 0 5
273 0 6
273 0 8
273 0 10
273 0 32
273 0 37
From the left to the right represents Julian day, hour in UTC, and minute when a tip of a rain gauge was made.
I need to calculate 5 minute totals and its accumulation of each day, for example, on the day 262 the rain tips total from 13-15 minute (since the information before 23:34 is not provided), 13-20 accumulated, 13-25, 13-30,... etc. Like I said each time recorded is when one tip was made and the precipitation amount of one tip is 0.01 inch. So all I need to know is how many tips were made within one day in 5 minute interval.
Could anyone help me please?

Perhaps something like this:
%# all possible days represented in the data
%# (you could also do this for all 1:365 days)
days = unique(X(:,1));
%# cumulative counts in each 5 minutes intervals
%# (each column represents one of the days)
counts = zeros(24*60/5,numel(days));
for i=1:numel(days)
%# indices of the instances in that day
idx = (X(:,1) == days(i));
%# convert hour/minute into minute units
m = X(idx,2).*60 + X(idx,3);
%# count occurences in each 5 minute bin
c = accumarray(fix(m/5)+1, 1, [24*60/5 1]);
%# take the cumulative sum and store it
counts(:,i) = cumsum(c);
end
so for day=262 we have:
>> counts(end-6:end,1)
ans =
0 %# [00:00, 23:30)
2 %# [00:00, 23:35)
6 %# [00:00, 23:40)
10 %# [00:00, 23:45)
14 %# [00:00, 23:50)
18 %# [00:00, 23:55)
21 %# [00:00, 00:00 of next day)

you can convert day-hour-min into minutes. Suppose your data is stored in an n-by-3 matrix called data (how original). Then
>> minutes = data * [24*60; 60; 1]; % counting minutes from the begining
Now you have to define the bins' edges (the intervals for summation):
>> edges = min(minutes) : 5 : max(minutes); % you might want to round the lower and upper limits to align with a 5 minute interval.
Use histc to count how many drops in each bin
>> drops = histc(minutes, edges);

Related

Change base of whole matrix

I want to change the base of a multiplication table to another base.
If I use
disp(dec2base((1:10).*(1:10)',7))
the numbers come flowing out individually. However I want them to stay in the exact position in the given matrix.
The numerical base is a display issue, numbers are always stored and manipulated in base 2 internally. So all you need to do is write a loop that displays the numbers in they way you want to. For example:
for ii=1:10
for jj=1:10
fprintf('%6s',dec2base(ii*jj,7));
end
fprintf('\n');
end
Output:
1 2 3 4 5 6 10 11 12 13
2 4 6 11 13 15 20 22 24 26
3 6 12 15 21 24 30 33 36 42
4 11 15 22 26 33 40 44 51 55
5 13 21 26 34 42 50 55 63 101
6 15 24 33 42 51 60 66 105 114
10 20 30 40 50 60 100 110 120 130
11 22 33 44 55 66 110 121 132 143
12 24 36 51 63 105 120 132 144 156
13 26 42 55 101 114 130 143 156 202
Storing base-7 representation of numbers as string array:
M = (1:10).*(1:10)';
out = strings(size(M));
for jj = 1:size(M,2)
for ii = 1:size(M,1)
out(ii,jj) = dec2base(M(ii,jj) ,7);
end
end

Implementing matching pursuit algorithm

I have implemented matching pursuit algorithm but i m unable to get the required result.
Here is my code:
D=[1 6 11 16 21 26 31 36 41 46
2 7 12 17 22 27 32 37 42 47
3 8 13 18 23 28 33 38 43 48
4 9 14 19 24 29 34 39 44 49
5 10 15 20 25 30 35 40 45 50];
b=[6;7;8;9;10];
n=size(D);
A1=zeros(n);
R=b;
H=10;
if(H <= 0)
error('The number of iterations needs to be greater then 0')
end;
for k=1:1:H
[c,d] = max(abs(D'*R)); %//'
A1(:,d)=D(:,d);
D(:,d)=0;
y = A1\b;
R = b-A1*y;
end
Output
y=
0.8889
0
0
0
0
0
0
0
0
0.1111
I should get only non-zero value at (2,1) and other values should be zero but I'm getting 2 non-zero value. Can you please help me find out where the error is?
Thanks.
I checked with:
http://www.scholarpedia.org/article/Matching_pursuit
Your functions need to be normalized!
D = D./repmat(sum(D,1),5,1);
I get the following algorithm:
D=[1 6 11 16 21 26 31 36 41 46
2 7 12 17 22 27 32 37 42 47
3 8 13 18 23 28 33 38 43 48
4 9 14 19 24 29 34 39 44 49
5 10 15 20 25 30 35 40 45 50];
D = D./repmat(sum(D,1),5,1);
b=[6;7;8;9;10];
n=size(D);
A1=zeros(n);
R=b;
H=100;
if(H <= 0)
error('The number of iterations needs to be greater then 0')
end;
a = zeros(1,H);
G = zeros(size(D,1),H);
for k=1:1:H
ip = D'*R;
[~,d] = max(abs(ip)); %//'
G(:,k) = D(:,d);
a(k) = ip(d);
R = R-a(k)*G(:,k);
end
% recover signal:
Rrec = zeros(size(R));
for i=1:H
Rrec = Rrec + a(i)*G(:,i);
end
figure();
plot(b);
hold on;
plot(Rrec)
It approximates the signal quite well. But not with D(:,2) at first as expected. Maybe it is a starting point...
Here is the updated code. This is based on the algorithm provided at https://en.wikipedia.org/wiki/Matching_pursuit
clc;
clear all;
D=[1 6 11 16 21 26 31 36 41 46
2 7 12 17 22 27 32 37 42 47
3 8 13 18 23 28 33 38 43 48
4 9 14 19 24 29 34 39 44 49
5 10 15 20 25 30 35 40 45 50];
b=[6;7;8;9;10];
H=10;
for index=1:10
G(:,index)=D(:,index)./norm(D(:,index));
end
G1=G;
n=size(G);
R=b;
if(H <= 0)
error('The number of iterations needs to be greater then 0')
end;
if(H >size(D,2))
error('The number of iterations needs to be less than dictionary size')
end;
bIndex=1:size(G,2);
for k=H:-1:1
innerProduct=[];
for index=1:size(G,2)
innerProduct(index)=dot(R,G(:,index));
end
[c,d] = max(abs(innerProduct));
An(H-k+1)=innerProduct(d);
R = R-(An(H-k+1)*G(:,d));
G(:,d)=[];
strong(H-k+1)=bIndex(d);
bIndex(d)=[];
end
G_new=G1(:,strong);
%% reconstruction
bReconstructed=zeros(size(G_new,1),1);
for index=1:size(G_new,2)
bReconstructed(:,index) = (An(index)*G_new(:,index));
end
b_new=sum(bReconstructed,2)
Yes the atoms in the dictionary must be normalized so that the inner products of the current residual with different atoms can be compared fairly.
You may want to check my OMP implementation which also includes incremental Cholesky updates for the least square step in OMP at https://github.com/indigits/sparse-plex/blob/master/library/%2Bspx/%2Bpursuit/%2Bsingle/omp_chol.m
I have written detailed tutorial notes on OMP in my library documentation at https://sparse-plex.readthedocs.io/en/latest/book/pursuit/omp/index.html
My library sparse-plex contains a C implementation of OMP which is close to 4 times faster than fastest MATLAB implementations. See the discussion here https://sparse-plex.readthedocs.io/en/latest/book/pursuit/omp/fast_omp.html

Stacked-area with date format at x-axis on Gnuplot

I have created graphs using filledcurves. Now, the graphs looks bad because long range of data.
This is my data:
a b c d e f g h i
201312 49 26 34 30 14 25 9 4 1
201311 38 22 47 30 9 9 4 3 1
201310 44 24 43 38 9 14 5 7 0
201309 65 18 33 39 15 12 4 5 1
201308 42 31 44 30 5 11 0 2 2
201307 58 27 35 29 8 4 2 4 2
201306 30 22 15 17 2 6 3 4 0
201305 61 52 20 16 11 12 2 3 0
201304 62 60 33 18 13 9 5 6 0
201303 43 53 49 27 9 11 7 0 0
201302 31 30 42 27 10 8 4 2 0
201301 42 30 20 47 9 13 3 2 1
201212 26 19 39 24 9 11 0 0 0
201211 26 26 30 28 1 2 0 2 1
201210 55 46 34 30 13 5 0 2 1
201209 56 31 27 28 27 13 2 4 1
201208 48 75 38 46 22 10 0 1 0
201207 60 56 37 47 19 11 2 1 0
201206 60 41 37 28 17 12 5 1 0
201205 49 43 38 46 15 16 2 2 0
201204 43 50 36 33 4 7 3 0 2
201203 49 63 35 43 16 7 1 2 0
201202 43 59 59 52 16 13 3 4 1
201201 51 44 30 37 20 9 4 1 0
201112 50 38 36 36 8 2 3 1 1
201111 75 35 30 36 16 7 3 3 1
201110 68 53 41 27 11 15 1 2 1
201109 68 46 48 47 16 19 4 0 1
201108 45 41 20 36 17 10 1 0 0
201107 48 34 30 24 13 7 3 3 1
201106 49 29 24 25 5 6 0 3 0
201105 45 35 21 37 1 7 2 1 0
201104 53 35 23 18 4 6 1 5 1
201103 58 42 20 18 6 4 1 0 4
201102 54 32 19 20 4 10 0 2 0
201101 42 41 21 28 3 6 1 2 1
and this is my gnuplot file:
set terminal postscript eps color font 20
set xtics 1 out
set tics front
#set style fill transparent solid 0.5 noborder
set key below autotitle columnheader
set ylabel "Count"
set xlabel "across time"
set output 't1.eps'
set title "t1-Across time of Aspects"
set xtics 1
plot for [i=10:2:-1] \
"< awk 'NR==1 {print \"year\",$".(i-1)."} NR>=2 {for (i=2; i<=".i."; i++) \
{sum+= $i} {print $1, sum; sum=0} }' data.dat" \
using (column(2)):xtic(1) with filledcurves x1 t column(2)
When I add time in xdata:
set xdata time
set timefmt "%Y%m"
set xtics format "%b"
Erros message:
Need full using spec for x time data
Is the Errors because of my date format? I have googling this and do not have any answer about it. Please give me suggestion about this.
In the script you show, you specify only a single column in the using statement (besides the xtic). That means, that this value is taken as y-value and the row number is implicitely used as x-value.
When using time data, you must explicitely specify all columns which are needed for the plotting style, there is no assumption about what might be the first column. Use:
set key below autotitle columnheader
set ylabel "Count"
set xlabel "across time"
set tics front
set xdata time
set timefmt "%Y%m"
set xtics format "%b'%y"
set autoscale xfix
plot for [i=10:2:-1] \
"< awk 'NR==1 {print \"year\",$".(i-1)."} NR>=2 {for (i=2; i<=".i."; i++) \
{sum+= $i} {print $1, sum; sum=0} }' data.dat" \
using 1:2 with filledcurves x1 t column(2)
Result with 4.6.4:
I guess you don't want xtic(1) if you have time data and specify the x format.

Ask for MATLAB code to detect steady state of data

I have a vector of electrical power consumption data which consists of transient, steady and power off states. I would like to identify steady-state starting point by the following condition:
The 5 consecutive elements of the data have difference values between each adjacent element <= threshold value (for this case, let say =10 W)
The first element that meets the condition shows the starting point of steady-state.
Example:
data = [0 0 0 40 70 65 59 50 38 30 32 33 30 33 37 19 ...
0 0 0 41 73 58 43 34 25 39 33 38 34 31 35 38 19 0]
abs(diff(data)) = [0 0 40 30 15 7 9 12 8 3 2 1 3 4 18 19 ...
0 0 41 32 15 9 14 6 5 4 3 4 3 19 19 0]
The sequences of abs(diff(data)) that meet the condition are 8 3 2 1 3 and 6 5 4 3 4. Therefore, the output should show the 10th data element (=30) and 27th data element (=33) as starting point of steady-state (There are 2 times of steady-state detected).
How would I write MATLAB code for this scenario?
(PS: data = 0 shows power off state)
Here's one approach using nlfilter (if the function is not available, you can implement a sliding window yourself):
data = [0 0 0 40 70 65 59 50 38 30 32 33 30 33 37 19 0 0 0 41 73 58 43 34 25 39 33 38 34 31 35 38 19 0];
difs = abs(diff(data));
% Use sliding window to find windows of consecutive elements below threshold
steady = nlfilter(difs, [1, 5], #(x)all(x <= 10));
% Find where steady state starts (1) and ends (-1)
start = diff(steady);
% Return indices of starting steady state
ind = find(start == 1);

Matlab: sum column elements with restrictions

We have a MxN matrix and a constrain cstrn = 100;.
The constrain is the summarize limit of column's elements (per column):
sum(matrix(:,:))<=cstrn.
For a given example as the following:
Columns 1 to 5:
15 18 -5 22 19
50 98 -15 39 -8
70 -15 80 45 38
31 52 9 80 72
-2 63 52 71 6
7 99 32 58 41
I want to find the max number of element per column who fulfill this constrain.
How can i summarize every column element with the others elements in same column and find which sum combinations uses the max number of elements per column?
In the given example solution is:
4 3 5 2 5
where
column 1: 15 + 50 + 31 +7 +(-2)
column 2: 18 +(-15) + 52 or 63 etc.
Thank you in advance.
Since it is always easier to fit small elements into a sum, you can do a sort, followed by the cumulative sum:
m= [
15 18 -5 22 19
50 98 -15 39 -8
70 -15 80 45 38
31 52 9 80 72
-2 63 52 71 6
7 99 32 58 41];
cs = cumsum(sort(m))
cs =
-2 -15 -15 22 -8
5 3 -20 61 -2
20 55 -11 106 17
51 118 21 164 55
101 216 73 235 96
171 315 153 315 168
Now you easily identify at which element you cross the threshold cnstrn (thanks, #sevenless)!
out = sum(cs <= cnstrn)
out =
4 3 5 2 5
I'd add to Jonas's answer, that you can impose your constraint in a way that outputs a logical matrix then sum over the 1's and 0's of that matrix like so:
cstrn = 100
m= [
15 18 -5 22 19
50 98 -15 39 -8
70 -15 80 45 38
31 52 9 80 72
-2 63 52 71 6
7 99 32 58 41];
val_matrix = cumsum(sort(m))
logical_matrix = val_matrix<=cstrn
output = sum(logical_matrix)
Giving output:
cstrn =
100
val_matrix =
-2 -15 -15 22 -8
5 3 -20 61 -2
20 55 -11 106 17
51 118 21 164 55
101 216 73 235 96
171 315 153 315 168
logical_matrix =
1 1 1 1 1
1 1 1 1 1
1 1 1 0 1
1 0 1 0 1
0 0 1 0 1
0 0 0 0 0
output =
4 3 5 2 5
Here is a logic, on mobile so can't give a code.
Check this out. Go to a column, sort it ascending order, loop to sum, break when hits <=100. Get counter. Refer back to original column, get the indices of elements matching the elements you just summed up :-)