I want to insert the symbol +- (\pm) between x and y in table created in matlab
x = (1:1:5)';
y = x*5/100;
table = [x y]
So, that the output is
1.0000 +/- 0.0500
2.0000 +/- 0.1000
3.0000 +/- 0.1500
4.0000 +/- 0.2000
5.0000 +/- 0.2500
If we can also write the minus exactly below plus.
You can use unicode characters in MATLAB. The following works:
>> fprintf('%f ± %f\n', table.')
1.000000 ± 0.050000
2.000000 ± 0.100000
3.000000 ± 0.150000
4.000000 ± 0.200000
5.000000 ± 0.250000
Note that fprintf cycles through all the elements of the input matrix in storage order (down the first column first). So it was necessary to transpose the data array (table.') to print it in one command.
This works for printing to file as well on MacOS:
f = fopen('mytextfile.txt','wt');
fprintf(f,'%f ± %f\n', table.');
fclose(f);
With output as a text file use the format spec for fprintf such as
FileID=fopen('FileName.txt','w');
fprintf(FileID,['%1.4f ',177,' %1.4f\n'],[x';y'])
fprintf(['%0.2f ' char(177) ' %0.2f\n'], [x;y]);
Related
i have this code in octave for the runge kutta of the 4th order method but i cant create a graph
dy=#(x,y)-x^2+2*y;
f=#(x)exp(x^2/2);
a=0;
b=2;
y=1;
y0=1;
m=20;
h=(b-a)/m;
k=0;
fprintf('k \t x \t\t y (RK4) \t k1 \t\t k2 \t\t k3 \t\t k4 \n')
fprintf('%d \t %f \t %f \t\n', k,a,y);
for x=a:h:b-h
k1=dy(x,y)*h;
k2=dy((x+h)/2,(y+k1)/2)*h;
k3=dy((x+h)/2,(y+k2)/2)*h;
k4=dy((x+h)/2,(y+k3)/2)*h;
k=k+1;
y=y+dy(x,y)*h;
x=x+h;
fprintf('%d \t %f \t %f \t %f \t %f \t %f \t %f \t \n', k,x,y,k1,k2,k3,k4);
end
fprintf('yn= %f \n',RK4("fedo",a,b,y0,m));
fprintf('Eroarea comisa este de ordinul lui %d \n',h^2);
and i need to create a graph but i dont know what to plot
help?
First, there is an undefined RK4 function in your fprintf statements that doesn't allow us to see the full printed output you desired, but your other code runs, and it looks like the last line is just printing the error estimate. Let's look at the output that does display:
k x y (RK4) k1 k2 k3 k4
0 0.000000 1.000000
1 0.100000 1.200000 0.200000 0.119750 0.111725 0.110923
2 0.200000 1.439000 0.239000 0.142900 0.133290 0.132329
3 0.300000 1.722800 0.283800 0.170030 0.158653 0.157515
4 0.400000 2.058360 0.335560 0.201836 0.188464 0.187126
5 0.500000 2.454032 0.395672 0.239153 0.223501 0.221936
6 0.600000 2.919838 0.465806 0.282984 0.264702 0.262873
7 0.700000 3.467806 0.547968 0.334531 0.313187 0.311053
8 0.800000 4.112367 0.644561 0.395237 0.370304 0.367811
9 0.900000 4.870841 0.758473 0.466834 0.437670 0.434754
10 1.000000 5.764009 0.893168 0.551401 0.517224 0.513806
11 1.100000 6.816811 1.052802 0.651431 0.611294 0.607280
12 1.200000 8.059173 1.242362 0.769917 0.722673 0.717948
13 1.300000 9.527007 1.467835 0.910451 0.854712 0.849139
14 1.400000 11.263409 1.736401 1.077341 1.011435 1.004844
15 1.500000 13.320091 2.056682 1.275759 1.197667 1.189858
16 1.600000 15.759109 2.439018 1.511911 1.419200 1.409929
17 1.700000 18.654931 2.895822 1.793243 1.682985 1.671959
18 1.800000 22.096917 3.441986 2.128692 1.997362 1.984229
19 1.900000 26.192300 4.095383 2.528980 2.372340 2.356676
20 2.000000 31.069760 4.877460 3.006976 2.819928 2.801223
There is a lot here that you could plot. But there's a small problem here, which is that all of that data is not saved in any variables. It's just printed to the screen and then overwritten on the next iteration of your RK loop. For example, after the program runs your workspace contains the following variables:
>> whos
Variables visible from the current scope:
variables in scope: top scope
Attr Name Size Bytes Class
==== ==== ==== ===== =====
a 1x1 8 double
b 1x1 8 double
dy 1x1 0 function_handle
f 1x1 0 function_handle
h 1x1 8 double
k 1x1 8 double
k1 1x1 8 double
k2 1x1 8 double
k3 1x1 8 double
k4 1x1 8 double
m 1x1 8 double
x 1x1 8 double
y 1x1 8 double
y0 1x1 8 double
>> k1
k1 = 4.8775
where all of the variables only retain the last value, k1 shown as an example.
If you want to plot the information, you need to retain the information to plot. if I manually copied/pasted your data into the terminal to define a data variable (ignoring the first partial line):
>> data = [1 0.100000 1.200000 0.200000 0.119750 0.111725 0.110923
2 0.200000 1.439000 0.239000 0.142900 0.133290 0.132329
3 0.300000 1.722800 0.283800 0.170030 0.158653 0.157515
4 0.400000 2.058360 0.335560 0.201836 0.188464 0.187126
5 0.500000 2.454032 0.395672 0.239153 0.223501 0.221936
6 0.600000 2.919838 0.465806 0.282984 0.264702 0.262873
7 0.700000 3.467806 0.547968 0.334531 0.313187 0.311053
8 0.800000 4.112367 0.644561 0.395237 0.370304 0.367811
9 0.900000 4.870841 0.758473 0.466834 0.437670 0.434754
10 1.000000 5.764009 0.893168 0.551401 0.517224 0.513806
11 1.100000 6.816811 1.052802 0.651431 0.611294 0.607280
12 1.200000 8.059173 1.242362 0.769917 0.722673 0.717948
13 1.300000 9.527007 1.467835 0.910451 0.854712 0.849139
14 1.400000 11.263409 1.736401 1.077341 1.011435 1.004844
15 1.500000 13.320091 2.056682 1.275759 1.197667 1.189858
16 1.600000 15.759109 2.439018 1.511911 1.419200 1.409929
17 1.700000 18.654931 2.895822 1.793243 1.682985 1.671959
18 1.800000 22.096917 3.441986 2.128692 1.997362 1.984229
19 1.900000 26.192300 4.095383 2.528980 2.372340 2.356676
20 2.000000 31.069760 4.877460 3.006976 2.819928 2.801223];
Then I can plot all sorts of things, like y vs k, or y vs x, etc:
plot (data(:,1), data(:,3)); title ("y vs k");
figure
plot (data(:,2), data(:,3)); title ("y vs x");
So the big question is how to retain your data so you aren't reliant on copy/paste.
Octave and Matlab variables are arrays. In your case, the variables you store your data in are single element, 1x1 arrays, and you overwrite them every iteration. An alternative approach is to use a vector for each variable (just as your printed output appears), and to store values from each iteration in a different vector location, indexed by k.
I notice that some of your variables you print are actually not the variables you use for each step. E.g., for k = 1, you print x = 0.1 but all of those values are calculated with k= 0 and x = 0. You then increment x and k right before printing. So some of those details might need to be tweaked to get what you want to match with what follows:
Since you're using x to define your steps, you probably want to expand that to an array first:
>> x=[a:h:b-h];
>> x'
x =
0
0.1000
0.2000
0.3000
0.4000
0.5000
0.6000
0.7000
0.8000
0.9000
1.0000
1.1000
1.2000
1.3000
1.4000
1.5000
1.6000
1.7000
1.8000
1.9000
(Note the vector is normally a row vector, I used a ' (transpose operator) to makes it display as a column vector here. I do the same at the end for storing results.)
The following rewritten RK loop produces an output much like your previous output:
x=[a:h:b];
for k = 1:length(x)-1
k1(k+1) = dy(x(k),y(k))*h;
k2(k+1) = dy((x(k)+h)/2,(y(k)+k1(k+1))/2)*h;
k3(k+1) = dy((x(k)+h)/2,(y(k)+k2(k+1))/2)*h;
k4(k+1) = dy((x(k)+h)/2,(y(k)+k3(k+1))/2)*h;
y(k+1) = y(k) + dy(x(k),y(k))*h;
end
data = [x',y',k1',k2',k3',k4']
data =
0 1.0000 0 0 0 0
0.1000 1.2000 0.2000 0.1198 0.1117 0.1109
0.2000 1.4390 0.2390 0.1429 0.1333 0.1323
0.3000 1.7228 0.2838 0.1700 0.1587 0.1575
0.4000 2.0584 0.3356 0.2018 0.1885 0.1871
0.5000 2.4540 0.3957 0.2392 0.2235 0.2219
0.6000 2.9198 0.4658 0.2830 0.2647 0.2629
0.7000 3.4678 0.5480 0.3345 0.3132 0.3111
0.8000 4.1124 0.6446 0.3952 0.3703 0.3678
0.9000 4.8708 0.7585 0.4668 0.4377 0.4348
1.0000 5.7640 0.8932 0.5514 0.5172 0.5138
1.1000 6.8168 1.0528 0.6514 0.6113 0.6073
1.2000 8.0592 1.2424 0.7699 0.7227 0.7179
1.3000 9.5270 1.4678 0.9105 0.8547 0.8491
1.4000 11.2634 1.7364 1.0773 1.0114 1.0048
1.5000 13.3201 2.0567 1.2758 1.1977 1.1899
1.6000 15.7591 2.4390 1.5119 1.4192 1.4099
1.7000 18.6549 2.8958 1.7932 1.6830 1.6720
1.8000 22.0969 3.4420 2.1287 1.9974 1.9842
1.9000 26.1923 4.0954 2.5290 2.3723 2.3567
2.0000 31.0698 4.8775 3.0070 2.8199 2.8012
(Also note octave and matlab start indexing at 1 not zero, hence all the k+1's)
Now that all of the data is stored and retained in the individual variable vectors or in the data array, you can make any plots you want. Recommend you check out the Octave manual section on plotting.
Is there a way to calculate a moving mean in a way that the values at the beginning and at the end of the array are averaged with the ones at the opposite end?
For example, instead of this result:
A=[2 1 2 4 6 1 1];
movmean(A,2)
ans = 2.0 1.5 1.5 3.0 5 3.5 1.0
I want to obtain the vector [1.5 1.5 1.5 3 5 3.5 1.0], as the initial array element 2 would be averaged with the ending element 1.
Generalizing to an arbitrary window size N, this is how you can add circular behavior to movmean in the way you want:
movmean(A([(end-floor(N./2)+1):end 1:end 1:(ceil(N./2)-1)]), N, 'Endpoints', 'discard')
For the given A and N = 2, you get:
ans =
1.5000 1.5000 1.5000 3.0000 5.0000 3.5000 1.0000
For an arbitrary window size n, you can use circular convolution with an averaging mask defined as [1/n ... 1/n] (with n entries; in your example n = 2):
result = cconv(A, repmat(1/n, 1, n), numel(A));
Convolution offers some nice ways of doing this. Though, you may need to tweak your input slightly if you are only going to partially average the ends (i.e. the first is averaged with the last in your example, but then the last is not averaged with the first).
conv([A(end),A],[0.5 0.5],'valid')
ans =
1.5000 1.5000 1.5000 3.0000 5.0000 3.5000 1.0000
The generalized case here, for a moving average of size N, is:
conv(A([end-N+2:end, 1:end]),repmat(1/N,1,N),'valid')
I am trying to compute a moving average on multiple columns of a matrix. After reading some answers on stackoverflow, namely this one, it seemed that the filter function was the way to go. However, it does not ignore NaN elements, and I would like to do this ignoring NaN elements in the spirit of the function nanmean. Below a sample code:
X = rand(100,100); %generate sample matrix
X(sort(randi([1 100],1,10)),sort(randi([1 100],1,10))) = NaN; %put some random NaNs
windowlenght = 7;
MeanMA = filter(ones(1, windowlenght) / windowlenght, 1, X);
Use colfilt with nanmean:
>> A = [1 2 3 4 5; 2 nan nan nan 6; 3 nan nan nan 7; 4 nan nan nan 8; 5 6 7 8 9]
A =
1 2 3 4 5
2 NaN NaN NaN 6
3 NaN NaN NaN 7
4 NaN NaN NaN 8
5 6 7 8 9
>> colfilt(A, [3,3], 'sliding', #nanmean)
ans =
0.6250 1.1429 1.5000 2.5714 1.8750
1.1429 2.2000 3.0000 5.0000 3.1429
1.5000 3.0000 NaN 7.0000 3.5000
2.5714 5.0000 7.0000 7.8000 4.5714
1.8750 3.1429 3.5000 4.5714 3.1250
(if you only care about 'full' blocks, select inner rows / columns appropriately)
Alternatively, you can also use nlfilter, but you then need to be explicit (via an anonymous function handle) about what you'll be doing with the block; in particular, to work with nanmean such that it will produce a scalar output from the whole block, you'll need to convert each block to a column-vector before calling nanmean in your anonymous function:
>> nlfilter(A, [3,3], #(x) nanmean(x(:)))
ans =
0.6250 1.1429 1.5000 2.5714 1.8750
1.1429 2.2000 3.0000 5.0000 3.1429
1.5000 3.0000 NaN 7.0000 3.5000
2.5714 5.0000 7.0000 7.8000 4.5714
1.8750 3.1429 3.5000 4.5714 3.1250
However, for the record, matlab claims colfilt will generally be faster, so generally nlfilter is better reserved for situations where it doesn't make sense for your input to be converted to a column when processing each block.
Also see matlab's manual page/chapter on sliding operations in general.
If you have R2016a or beyond, you can use the movmean function with the 'omitnan' option.
Try
MeanMA = filter(ones(1, windowlenght) / windowlenght, 1, X(find(~isnan(X)));
This will extract the non-nan values from X.
The question is... do you still have a valid filter processing? If X is filled iteratively, one element per timestep, then the "NaN-Elimination" will produce a shorter vector which values are not aligned with the original time vector any more.
EDIT
To still have a valid mean calculation, the filter parameters must be updated according to the number of non-NaN values.
values = X(find(~isnan(X));
templength = length(values);
MeanMA = filter(ones(1, templength ) / templength , 1, values );
So I have this data I'd like plotted on loglog scale, with linear values on the y-axis and the values in dB on the x axis and
loglog(EbN0,BER)
outputs a nice looking curve, but the problem is the axis ticks. It's fine on the y-axis, but the x axis only has one tick, at 10^0and no other ticks. Furthermore, that tick corresponds to the absolute value, not the dB value. Any convenient way to accomplish this?
(Note that both EbN0 and BER contain absolute values)
EDIT: I'll add my data and explain what I want a bit more.
EbN0 =
Columns 1 through 14
0.5000 1.0000 1.5000 2.0000 2.5000 3.0000 3.5000 4.0000 4.5000 5.0000 5.5000 6.0000 6.5000 7.0000
Columns 15 through 20
7.5000 8.0000 8.5000 9.0000 9.5000 10.0000
BER_TOT_ITER =
Columns 1 through 14
0.2928 0.2024 0.1183 0.0511 0.0164 0.0046 0.0010 0.0003 0.0001 0 0.0000 0.0000 0.0000 0
Columns 15 through 20
0 0 0 0 0 0
If I do plot(10*log10(EbN0),10*log10(BER_TOT_ITER)), I actually get exactly the graph I want and the dB values on the x axis, but now the y ticks are displayed in dB's instead of absolute values... so I just want to relabel the y ticks, NOT rescale the figure.
Relabeling the ticks is really the wrong approach here. You'd replace numerical values with strings and resizing etc. wouldn't work anymore.
Also your data does not fit to what you're actually looking at.
You should always try to transform your data first.
So besides loglog have a look at semilogx and semilogy, which allow you to have a single logarithmic axis.
To sum up, what you're looking for is:
semilogy(10*log10(EbN0), BER_TOT_ITER)
Is there anyway to read with subsampling in MATLAB? The input data look like:
id=3,age=25, 0.5 0.5 0.2 0.6 0.6 0.5
id=1,age=15, 0.5 0.8 0.2 0.9 0.6 0.9
id=7,age=24, 0.5 0.2 0.9 0.6 0.1 0.5
(Edited) For the LAST SIX columns, I only want columns that are multiple of three (i.e. the 3rd column and the 6th column in the LAST SIX COLUMNS, which is equivalent to the 5th column and the 8th column in the whole data file) be read. That is, a matrix like:
0.2 0.5
0.2 0.9
0.9 0.5
Ideally, the code looks like:
for line=1:maxLine
header(line,:) = fscanf(fid,'id=%d,age=%d,',[1,2]);
content(line,:) = fscanf(fid,'only read columns multiple of three');
end;
I know that I can read the whole line and sub-sample, the problem is, the array I'm dealing with has large scale, 10k+ columns, I do not want to consume too much memory.
There is the way:
if you use fopen you can get access to file only one time, so you can't do it in a loop. So you need to load all necessary data in one array and then transpose it.
Your desire to save free memory is achieved by ignoring some elements:
fid = fopen('new.txt','r');
A = fscanf(fid, 'id=%d,age=%d, %*f %*f %f %*f %*f %f\n', [4 inf])
I used your data and get this result:
A =
3.0000 1.0000 7.0000
25.0000 15.0000 24.0000
0.2000 0.2000 0.9000
0.5000 0.9000 0.5000
as you can read here http://www.mathworks.com/help/matlab/ref/fscanf.html?searchHighlight=fscanf fscanf reads data into columns, that is why we need to transpose it.
So using A=A' gives result you want:
A =
3.0000 25.0000 0.2000 0.5000
1.0000 15.0000 0.2000 0.9000
7.0000 24.0000 0.9000 0.5000
Now you can make two different matrices if needed.