Está en la página 1de 53

Opciones ms importantes en un grfico de 2 dimensiones

En la siguiente entrada resumo algunas de las opciones ms importantes, a la


hora de editar un grfico.
Como ejemplo, vamos a representar la curva siguente:
y = Asin(t/T + )

En un principio, podemos escribir algo as:


t = [0:0.01:4]';
y = 1.2*sin(2*pi*t/12);
figure(1)
hold on
box on
plot(t,y,'-r')

Este grfico est bastante pobre y se puede mejorar bastante. Por cierto, una
de las cosas que menos me gusta, es que las cifras significativas cambian en
los ejes.
figure(1)
hold on
box on

plot(t,y,'-','LineWidth',2,'Color',[1 0 0])
axis ([0 4 0 1.5])
xlabel('x')
ylabel('y')
title('y = 1.2 \cdot sin (2\pi /12 \cdot (t + \phi))')
set(gca,'XTick',[0:1:4])
set(gca,'XTickLabel',{'0','1','2','3','4'})
set(gca,'YTick',[0:0.5:1.5])
set(gca,'YTickLabel',{'0.0','0.5','1.0','1.5'})
set(gca,'Fontsize',10)
set(gca,'XGrid','on','YGrid','on')
legend({'\phi = 0'},2,'FontSize',10,'EdgeColor',[1 1 1]);

- Con "'XTickLabel',{}", editamos los nmeros de cada eje (x en este caso). En


vez de nmeros, usamos strings, y solucionamos a mano el problema de las
cifras significativas.
- Con "'EdgeColor',[1 1 1]" ponemos en blanco la caja de la leyenda.
- Las letras griegas y muchos smbolos matemticos se pueden poner con los
mismos comandos de LaTeX (como se ve en el ttulo).
- El nmero "2" en la leyenda, corresponde al segundo cuadrante. Se puede
poner 1, 2, 3 o 4.
- Se puede elegir entre varios tipos de lnea distintos: - : -- -.

El resto de comandos, creo que son bastante intuitivos.


Por cierto, Matlab distorsiona las distancias relativas de cada eje. Para poner
los ejes en la misma escala, se puede poner "axis equal".

Si queremos representar puntos sueltos, algunas de las opciones que podemos


editar son el tamao, grosor y relleno:
t = [0.5:0.5:3.5]';
y1 = 1.2*sin(2*pi*t/12);
y2 = 1.2*sin(2*pi*(t+1)/12);
figure(1)
hold on
box on
plot(t,y1,'o','MarkerSize',10,'LineWidth',2,'Color',[1 0 0])
plot(t,y2,'o','MarkerSize',5,'Color',[0 0 1],'MarkerFaceColor',[0 0 1])

Se puede elegir entre varios tipos de puntos: . o x + * s d v ^ < > p h

A veces queremos representar, adems del valor, su error asociado. En vez de


plot, usamos "errorbar".
t = [0.5:0.5:3.5]';
y1 = 1.2*sin(2*pi*t/12);
n = length(t);
xe = 0.05*rand(n,1)+ 0.05;
figure(1)
errorbar(t,y1,xe,'.','MarkerSize',5,'LineWidth',0.5,'Color',[1 0 0])

Otras posibilidades que tenemos, son el rea bajo la curva, barras para cada
punto, o una curva en forma de escalera:
t = [0.5:0.5:3.5]';
y = 1.2*sin(2*pi*t/12);
figure(1)
area(t,y,'FaceColor',[0.17 0.50 0.34]);

figure(1)
bar(t,y,'FaceColor',[0.7 0.8 1]);

figure(1)
stairs(t,y,'Color',[0.6 0.2 0],'LineWidth',2);

Por ltimo, muestro dos ejemplo de cmo representar varias curvas distintas,
usando un bucle for. Fjate, cmo defino la leyenda y los distintos colores para
cada curva.
phi = [0 1 2 3 4 5 6];
n = length(phi);
colores = [1 0 0; 1 0.6 0.2; 0.75 0.75 0; 0.17 0.51 0.34; 0.04 0.52 0.78; 0 0.75
0.75; 0.48 0.06 0.89];
t = [0:0.01:4]';
q = cell(1,n);
figure(2)
hold on
box on
for i=1:1:n
y = 1.2*sin(2*pi*(t+phi(i))/12);
plot(t,y,'-','LineWidth',2,'Color',colores(i,:))
q(i) = {['\phi = ' mat2str(phi(i))]};
end
axis([0 4 -1.5 1.5])
xlabel('x')

ylabel('y')
title('y = 1.2 \cdot sin (2\pi /12 \cdot (t + \phi))')
set(gca,'XTick',[0:1:4])
set(gca,'XTickLabel',{'0','1','2','3','4'})
set(gca,'YTick',[-1.5:0.5:1.5])
set(gca,'YTickLabel',{'-1.5','-1.0','-0.5','0.0','0.5','1.0','1.5'})
set(gca,'Fontsize',10)
set(gca,'XGrid','on','YGrid','on')
legend(q,3,'FontSize',10)

phi = [0:0.5:7.5];
phitext = {'0.0','0.5','1.0','1.5','2.0','2.5',...
'3.0','3.5','4.0','4.5','5.0','5.5',...
'6.0','6.5','7.0','7.5'}
n = length(phi);
colores = [1 0 0; 1 0.6 0.2; 0.75 0.75 0; 0.17 0.51 0.34; 0.04 0.52 0.78; 0 0.75
0.75; 0.48 0.06 0.89];
t = [0:0.01:4]';
nt = length(t);
q = cell(1,n);
figure(1)
set(0,'DefaultAxesColorOrder',colores, 'DefaultAxesLineStyleOrder','-|--|:')
hold on

box on
y = zeros(nt,n);
for i=1:1:n
y(:,i) = 1.2*sin(2*pi*(t+phi(i))/8);
q(i) = {['\phi = ' cell2mat(phitext(i))]};
end
plot(t,y)
axis([0 4 -1.5 1.5])
xlabel('x')
ylabel('y')
title('y = 1.2 \cdot sin (2\pi /8 \cdot (t + \phi))')
set(gca,'XTick',[0:1:4])
set(gca,'XTickLabel',{'0','1','2','3','4'})
set(gca,'YTick',[-1.5:0.5:1.5])
set(gca,'YTickLabel',{'-1.5','-1.0','-0.5','0.0','0.5','1.0','1.5'})
set(gca,'Fontsize',10)
legend(q,'Location','EastOutside','FontSize',10)
- En este segundo caso, defino la secuencia de colores y tipo de curvas, que
van a ir teniendo las curvas. Luego, calculo una matriz con todas las curvas.
- En la leyenda, los valores de phi los calculo como strings, para poner
correctamente las cifras significativas.

Cmo aadir un eje secundario en un grfico

A veces resulta interesante representar en un mismo grfico dos curvas


distintas. Si estas curvas tienen distintas unidades o se mueven en un distinto
rango, habra que trabajar con dos ejes distintos. Esto se puede hacer
fcilmente con la funcin "plotyy". Sin embargo, si queremos editar los ejes, es
un poco ms complejo. En esta entrada, muestro cmo se puede hacer.
Por ejemplo, si quiero representar las dos curvas siguientes:
t = [0:0.05:10]';
y1 = sin(t);
y2 = 5*cos(2*pi*t/6);
Primero, defino los rangos, ticks, y colores de cada curva:
y1lim = [-1.5,1.5];
y1ticks = [-1.5:0.5:1.5];
y1tickslabel = {'-1.5','-1.0','-0.5','0.0','0.5','1.0','1.5'};
y1string = 'sin(t)';
y2lim = [-6,6] ;
y2ticks = [-6:2:6];
y2tickslabel = {'-6','-4','-2','0','2','4','6'};
y2string = '5\cdot cos(2\cdot \pi /6 \cdot t)';
x1lim = [0,10];
x1ticks = [0:2.5:10];
x1tickslabel = {'0.0','2.5','5.0','7.5','10.0'};
x1string ='time';
color1 = [0 0.2 0.9];
color2 = [0 0.5 0.1];
A continuacin, represento las dos curvas con el siguiente cdigo:
figure1 = figure(1);
axes1 = axes('Parent',figure1,...
'YTick',y1ticks,'YTickLabel',y1tickslabel,...
'XTick',[],...
'ColorOrder',[color2; color1],...
'YColor',color1,...
'Fontsize',10);

xlim(axes1,x1lim);
ylim(axes1,y1lim);
box(axes1,'on');
hold(axes1,'all');
plot(t,y1,'Parent',axes1,'LineWidth',1);
ylabel(y1string,'Color',color1);
axes2 = axes('Parent',figure1,...
'YTick',y2ticks,'YTickLabel',y2tickslabel,...
'XTick',x1ticks,'XTickLabel',x1tickslabel,...
'ColorOrder',[color1; color2],...
'YColor',color2,...
'Color','none',...
'Fontsize',10,...
'YAxisLocation','right');
xlim(axes2,x1lim);
ylim(axes2,y2lim);
hold(axes2,'all');
plot(t,y2,'Parent',axes2,'LineWidth',1);
ylabel(y2string,'Color',color2);
xlabel(x1string);
title('sinusoidales');

Nota: El eje de las x est pintado solo en "axes2". En "axes1" puse "'XTick',[]"
para que no escribiera nada. De no hacerlo as, el eje de las x se escribira dos
veces, uno sobre el otro, y quedara un poco feo.
Cmo dibujar crculos y polgonos regulares

Para dibujar un crculo con Matlab, una posibilidad muy fcil, es hacerlo en
coordenadas polares. Es decir:
R = 1;
tita = (0:0.01:2.01*pi);
x = R*cos(tita);
y = R*sin(tita);
figure(1)
plot(x,y,'-b')
axis equal
axis([-1.5 1.5 -1.5 1.5])
set(gca,'XTick',[-1.5:0.5:1.5])
set(gca,'XTickLabel',{'-1.5','-1.0','-0.5','0.0','0.5','1.0','1.5'})
set(gca,'YTick',[-1.5:0.5:1.5])
set(gca,'YTickLabel',{'-1.5','-1.0','-0.5','0.0','0.5','1.0','1.5'})
set(gca,'Fontsize',10)
Por cierto, el valor de "tita" lo llevo hasta 2.01*pi, en vez de hasta solo 2.00*pi,
para que el crculo se cierre (y no quede un pequeito espacio en blanco).
Adems, he puesto "axis equal" para evitar que Matlab distorsione los ejes.

En realidad, no hemos dibujo un crculo, sino un polgono de 630 lados. Lo que


a simple vista, es suficientemente parecido a un crculo.

Bueno, pues entonces, dibujar un polgono regular de n lados, se hace igual.


Por ejemplo, para un pentgono:

n = 5;
R = 1;
tita = [0:(2*pi/n):2*pi];
x = R*cos(tita);
y = R*sin(tita);
figure(1)
plot(x,y,'-b')
axis equal
axis([-1.5 1.5 -1.5 1.5])
set(gca,'XTick',[-1.5:0.5:1.5])
set(gca,'XTickLabel',{'-1.5','-1.0','-0.5','0.0','0.5','1.0','1.5'})
set(gca,'YTick',[-1.5:0.5:1.5])
set(gca,'YTickLabel',{'-1.5','-1.0','-0.5','0.0','0.5','1.0','1.5'})
set(gca,'Fontsize',10)

Para evitar que el pentgono est girado, podemos hacer que el valor de "tita"
empiece en /2:
n = 5;
R = 1;

tita = [0:(2*pi/n):2*pi]+pi/2;
x = R*cos(tita);
y = R*sin(tita);

Ahora ya es muy fcil hacer muchas figuras. Por ejemplo, una estrella de 5
puntas:
n = 5;
R = 1;
tita = [0:(4*pi/n):4*pi]+pi/2;
x = R*cos(tita);
y = R*sin(tita);

Cmo trasladar y girar una curva


Mover una curva es otra de las cosas ms sencillas de hacer. Por ejemplo, si
tenemos la siguiente curva que parte del punto (0,0) y queremos moverla al
punto (6,4), podemos hacer la siguiente transformacin:
% curva original
x = [0:0.1:4*pi];
y = sin(x);
% translacin al punto (6,4)
x1 = x + 6;
y1 = y + 4;
figure(1)
hold on
box on
plot(x,y,'-b')
plot(x1,y1,'-m')
axis equal
legend('original','movida',2)

Si lo que queremos es girar la curva un ngulo tita, la operacin tambin es


muy sencilla. Aplicamos la siguiente transformacin (que se calcula muy
facilmente por geometra). Por ejemplo, para un ngulo = /6 radianes:
% rotacion de tita radianes
tita = 2*pi/6;
x1 = (x-y*tan(tita))*cos(tita);
y1 = y/cos(tita) + (x-y*tan(tita))*sin(tita);
figure(2)
hold on
box on
plot(x,y,'-b')
plot(x1,y1,'-m')
axis equal
legend('original','girada')

Hay que tener cuidado, porque las ecuaciones anteriores no estn definidas si
vale /4 (/2) o mltiplos. En esos casos, hay que girar la curva directamente
de la forma:
% giro de 1/4 tau (1/2 pi) radianes
x1 = -y;
y1 = x;
% giro de 2/4 tau (pi) radianes

x2 = -x;
y2 = -y;
% giro de 3/4 tau (3/2 pi) radianes
x3 = y;
y3 = -x;
figure(3)
hold on
box on
plot(x,y,'-b')
plot(x1,y1,'-m')
plot(x2,y2,'-r')
plot(x3,y3,'-k')
legend('original','girada 1/4 \tau','girada 2/4 \tau', 'girada 3/4 \tau')

Cmo trabajar con coordenadas polares


Muchas funciones son ms fciles de ser representadas en coordenadas
polares. Por ejemplo, la cardiode:
= R(1+cos(+/4))
donde va de 0 a . (Ya sabes, = 2.)

Para dibujar una funcin en polares, podemos usar directamente la funcin


"polar", como muestro a continuacin:
R = 1;
tita = 0:0.01:2.0*pi;
rho = R*(1+cos(tita+pi/2));
figure(1)
polar(tita,rho,'m-')

Sin embargo, para editar el grfico, es ms fcil hacerlo en coordenadas


cartesianas. Para ello, primero transformamos las variables "tita" y "rho", en
cartesianas ("x" e "y"):
x = rho.*cos(tita);
y = rho.*sin(tita);
Y a continuacin, representamos "x" e "y" normalmente:
figure(1)
hold on

box on
plot(x,y,'-','LineWidth',2,'Color',[0.5 0.05 0.9])
axis equal
axis([-1.5 1.5 -2.5 0.5])
set(gca,'XTick',[-1.5:0.5:1.5])
set(gca,'XTickLabel',{'-1.5','-1.0','-0.5','0.0','0.5','1.0','1.5'})
set(gca,'YTick',[-2.5:0.5:0.5])
set(gca,'YTickLabel',{'-2.5','-2.0','-1.5','-1.0','-0.5','0.0','0.5'})
set(gca,'Fontsize',10)
Nota: La lnea "axis equal" es importante para que Matlab no deforme el
tamao de los ejes, como suele hacer por defecto
Por ltimo, si queremos aadir los ejes, podemos hacerlo directamente as:
plot([-2 2],[0 0],'--','Color',[0.5 0.5 0.5])
plot([0 0],[-3 2],'--','Color',[0.5 0.5 0.5])

Cmo dibujar la superficie de una curva en 3 dimensiones


En esta entrada, resumir las opciones ms importantes a la hora de dibujar
una curva en 3D. En el ejemplo, utilizo la funcin de Rosenbrock siguiente:
z = (1-x)2 + 2(y-x2)2
entre los siguientes lmites

-2 < x < 2
-1 < y < 2.5

En primer lugar, defino la funcin que voy a dibujar en el archivo "f01.m":


function z = f01(x,y)
z = (1-x).^2 + 2*(y-x.^2).^2;
A continuacin, creo tres matrices con los valores de "x" e "y", y los valores de
la funcin. El comando meshgrid transforma los vectores "x" e "y" en dos
matrices, que contienen todos los diferentes pares de puntos.
x = [-2:0.1:2];
y = [-1:0.1:2.5];
[X,Y] = meshgrid(x,y);
Z = f01(X,Y);
Nota: "x" es un vector de longitud 41. "y" es un vector de longitud 36. "X", "Y",
y "Z" son matrices de tamao 36x41.

La superficie la podemos dibujar directamente con el comando surf:


figure(1)
surf(X,Y,Z)
box on

Existen muchas opciones que se pueden configurar. Por ejemplo:

colormap spring % definimos el color (default, hot, spring, summer, autumn,


winter...)
daspect([3 2.5 60]);
axis([-2 2 -1 2.5 0 60])
xlabel('x')
ylabel('y')
zlabel('z')
title('funcin de Rosenbrock')
set(gca,'XTick',[-2:1:2])
set(gca,'XTickLabel',{'-2','-1','0','1','2'})
set(gca,'YTick',[-1:0.5:2.5])
set(gca,'YTickLabel',{'-1.0','-0.5','0.0','0.5','1.0','1.5','2.0','2.5'})
set(gca,'ZTick',[0:20:60])
set(gca,'ZTickLabel',{'0','20','40','60'})
set(gca,'Fontsize',10)

Nota: Con "daspect" definimos la relacin del tamao de los ejes.

Podemos definir el punto de vista del observador con la funcin "view". Por
ejemplo:
view([1 0 0])

Tambin podemos poner un foco de luz, para que la figura se vea ms bonita
light('Position',[0,2,50]) % Posicin del foco de luz
lighting phong % Para suavizar la luz
material metal % Distintos tipos de brillo (shiny, dull, metal...)

En vez de usar el comando "surf", podemos usar otro tipo de funciones. Por
ejemplo:

La funcin "mesh" muestra la superficie como una rejilla:


figure(1)
mesh(X,Y,Z)
box on

La funcin "contour" nos muestra el grfico en dos dimensiones, con isolneas.


Como se ve a continuacin, y donde "n" es el nmero de isolneas.
n = 75;
figure(1)
contour(X,Y,Z,n)
box on
colormap autumn
axis([-2 2 -1 2.5])
xlabel('x')
ylabel('y')
title('funcin de Rosenbrock')
set(gca,'XTick',[-2:1:2])
set(gca,'xTickLabel',{'-2','-1','0','1','2'})
set(gca,'YTick',[-1:0.5:2.5])
set(gca,'YTickLabel',{'-1.0','-0.5','0.0','0.5','1.0','1.5','2.0','2.5'})
set(gca,'Fontsize',10)

Podemos aadir una barra lateral con el valor de los colores:


colorbar('EastOutside', 'YTick',[0:20:60], 'YTickLabel',
{'0','20','40','60'},'Fontsize',10)
Nota: Como la barra la hemos puesto vertical, los nmeros de la barra los
definimos con 'YTick'. Si la hubiramos puesto horizontal (con 'SouthOutside',
deberamos haber usado 'XTick'...)

En vez de isolneas, tambin podramos haber usado solo colores en una

superficie, con el comando "surface":


figure(1)
surface(X,Y,Z)
box on
colormap default
axis([-2 2 -1 2.5])
xlabel('x')
ylabel('y')
title('funcin de Rosenbrock')
set(gca,'XTick',[-2:1:2])
set(gca,'xTickLabel',{'-2','-1','0','1','2'})
set(gca,'YTick',[-1:0.5:2.5])
set(gca,'YTickLabel',{'-1.0','-0.5','0.0','0.5','1.0','1.5','2.0','2.5'})
set(gca,'Fontsize',10)
colorbar('SouthOutside', 'XTick',[0:20:60], 'XTickLabel',
{'0','20','40','60'},'Fontsize',10)

Si trabajmos con "surf" o "surface", podemos suavizar el degrado de colores:


figure(1)
surface(X,Y,Z)
shading interp
box on

Cmo crear una matriz de colores en 3 dimensiones


Supongamos que quiero representar con colores una matriz. Donde el color de
cada celda, depende de su valor numrico. Es decir, quiero, de una matriz
como la siguiente:

f1

f2

v1

v2

v3

llegar a algo como esto:

Para ello, podra hacer algo similar a lo siguiente:

Primero, defino la matriz de datos, los ejes "x" e "y", y el estilo de colores:
A = [1 2 3; 4 5 6];
xticks = {'v1','v2','v3'};
yticks = {'f1','f2'};
estilo = 'copper';
Algunos estilos de colores posibles son 'default', 'copper', 'cool', 'spring',
'summer', 'autumn', 'winter'...

A continuacin, genero el grfico en colores de la forma siguiente:


[ny,nx] = size(A);
yticks = rot90(rot90(yticks));
figure(1)
hold on
for(i=1:1:nx)

for(j=1:1:ny)
X = [0 1; 0 1];
Y = [ny-1 ny-1; ny ny];
X = X + (i-1);
Y = Y - (j-1);
B = ones(2,2)*A(j,i);
surface(X,Y,B);
end
end
axis([0 nx 0 ny])
colormap(estilo)
set(gca,'XTick',[0.5:1:nx])
set(gca,'XTickLabel',xticks)
set(gca,'YTick',[0.5:1:ny])
set(gca,'YTickLabel',yticks)
set(gca,'Fontsize',10)
box on
Nota: Para girar el vector de strings "yticks" 180, he usado dos veces el
comando "rot90".

Para la barra lateral, utilizo los siguientes comandos:


colorbar('EastOutside', 'YTick',[1:1:6], 'YTicklabel',
{'1','2','3','4','5','6'},'Fontsize',10)
La barra anterior estaba vertical, y el eje se defina con "YTick". Si la barra
hubiera estado horizontal, habra que haberlo hecho con "XTick". Por ejemplo:
colorbar('SouthOutside', 'XTick',[1:1:6], 'XTicklabel',
{'1','2','3','4','5','6'},'Fontsize',10)
Como sabes, si pulsas el botn "Rotate 3D", puedes elegir el punto de vista que
ms te guste. En este caso, s que podramos tambin haber editado el eje de
las "z".
axis([0 nx 0 ny 0 6])
set(gca,'ZTick',[0:2:6])
set(gca,'ZTickLabel',{'0','2','4','6'})

Cmo ajustar un conjunto de puntos a un polinomio


Pocas cosas son ms fciles que ajustar un conjunto de puntos a un polinomio.
Por ejemplo, tenemos la siguiente serie de puntos, que queremos ajustar a un
polinomio de orden dos:
x = [1 2 3 4 5];
y = [3.6 7.1 9.1 11.3 12.5];

Para ello, usamos la funcin "polyfit":


n = 2;
alfa = polyfit(x,y,n)

alfa es un vector de tamao 3x1, formado por los coeficientes del polinomio:
y = alfa[1]x2 + alfa[2]x + alfa[3]
En este caso, alfa vale:
alfa =
-0.3143

4.0857 -0.0800

Para representar grficamente el polinomio correspondiente, podemos usar la


funcin "polyval", como muestro a continuacin:
x1 = [0:0.1:6];
y1 = polyval(alfa,x1);
figure(1)
hold on
box on
plot(x,y,'or')
plot(x1,y1,'-b')
axis([0 6 0 15])
legend('real','estimado',2)

Cmo ajustar un conjunto de datos a una funcin cualquiera


Tenemos un conjunto de puntos que queremos ajustar a una cierta funcin. Por
ejemplo, tenemos los puntos:
x = [1 2 3 4 5]';
y = [1.24 0.59 0.31 0.19 0.09]';

Y queremos ajustarlos a la funcin y = kexp(-ax). Para ello, tenemos que


estimar los parmetros "k" y "a".

Primero, creamos la funcin a ajustar en un archivo .m, por ejemplo "f01.m":


function z = f01(u,x)
z = u(1)*exp(-u(2)*x);
donde u(1) = k, y u(2) = a .
A continuacin, creamos la funcin objetivo que vamos a optimizar, y que
sume los errores al cuadro entre los valores medidos y los calculados. La
siguiente funcin la creamos en el archivo "fobj.m":
function z = fobj(u,x,ym)
ycal = f01(u,x);
z = sum((ym-ycal).^2);
Por ltimo, calculamos los parmetros "k" y "a" con la funcin "fminsearch":
[u,f] = fminsearch(@(u) fobj(u,x,y),[1 1])
donde [1 1] es el valor inicial de los parmetros, con los que el optimizador
empezar a buscar la solucin, la primera salida de la funcin "u" es un vector
con los parmetros estimados, y la segunda salida de la funcin "f" es el valor
de la funcin objetivo en el punto mnimo.
Matlab nos devuelve el siguiente resultado:
u=
2.4430
f=
0.0022

0.6864

En vez de usar "fminsearch" y tener que crear una funcin objetivo, podramos
haber usado directamente la funcion "lsqcurvefit". Pero la verdad, es que el
mtodo anterior me suele funcionar mejor.
[u,f] = lsqcurvefit(@(u,x) f01(u,x),[1,1],x,y)
donde [1 1] son los valores iniciales de u(1) y u(2), con los que la funcin
empieza a tantear. Por cierto, cuando escribimos @(u,x), hay que poner
primero el vector de parmetros a estimar, y segundo la variable
independiente.

Por ltimo, representamos tanto los puntos reales como la curva obtenida:
xx = [0:0.1:6];
yy = f01(u,xx);
figure(1)
hold on
box on
plot(xx,yy,'-','Color',[1 0.6 0.78],'LineWidth',2)
plot(x,y,'o','MarkerSize',5,'Color',[0.48 0.06 0.89],'MarkerFaceColor',[0.48 0.06
0.89])
legend({'real','estimado'},1,'EdgeColor',[1 1 1]);
axis([0 6 0 3])
set(gca,'XTick',[0:2:6])
set(gca,'YTick',[0:1:3])
set(gca,'Fontsize',10)
Nota: He usado 'EdgeColor',[1 1 1] para que la leyenda no est encerrada en
una caja. Y 'MarkerFaceColor',[0.48 0.06 0.89] para que los crculos estn
rellenos.

Cmo ajustar un conjunto de datos a una funcin definida en Simulink


Tenemos un conjunto de puntos. Por ejemplo, sean los puntos:
tm = [1 2 3 4 6 8 10 15]';
ym = [4.8 3.1 2.2 1.3 0.5 0.2 0.1 0.0]';
Y queremos aproximarlos a la siguiente funcin:

y' = -ky
y(0) = y0
Para lo que tenemos que estimar los parmetros "k" e "y0".
Como la funcin contiene una derivada, lo ms cmodo es definiarla usando
Simulink. Para ello, creamos el siguiente archivo "simu1.mdl" en Simulink:

- El bloque "Fcn", donde hemos definido la funcin, est en "User-Defined


Functions".
- El bloque "Integrator" est en "Continuous". Donde digo que la "Initial
condition source" es "external".
- Los bloques "Constant" y "Clock" estn en "Sources", mientras que el bloque
"To Workspace" est en "Sinks".
- En el bloque "To Workspace" defino el formato de salida como "Array" (no
"Structure" que es lo que viene por defecto). Adems, defino el nombre de la
variables de salida como "yout".
- En tiempo de simulacin hemos puesto la variable "tend". Antes de poder
ejecutar el programa, habr que definir el valor de "tend", "k" e "y0" en Matlab.
- Cuando ejecutamos este programa, Matlab, adems de calcular el vector
"yout" con el valor de la variable "y", tambin calcula el vector "tout", con el
valor del tiempo.

A continuacin creamos la funcin objetivo a minimizar, que calcula la suma de


los errores al cuadrado, para unos valores de "k" y "y0" dados. A este archivo le
damos el nombre "fobj1.m".

function z = fobj01(tm,ym,u)
global k y0
k = u(1);
y0 = u(2);
sim('simu1.mdl');
ycal = resample(timeseries(yout,tout),tm);
ycal = ycal.data;
clc
z = sum((ym - ycal).^2);

Finalmente, desde Matlab, ya podemos hacer la estimacin de parmetros.


Para ello escribimos:
tm = [1 2 3 4 6 8 10 15]';
ym = [4.8 3.1 2.2 1.3 0.5 0.2 0.1 0.0]';
tend = 20;
global k y0
[u,f] = fminsearch(@(u) fobj01(tm,ym,u),[1 1])
donde "u" es el valor de los parmetros estimados, y "f" es el valor de funcin
objetivo (suma de los error al cuadro.)

Matlab nos devuelve los siguientes valores:


u=
0.4247

f=
0.0309

7.3344

Por ltimo, podemos dibujar tanto los valores medidos como los estimados:
k = u(1);
y0 = u(2);
sim('simu1.mdl');
figure(1)
hold on
box on
plot(tout,yout,'-','Color',[1 0.6 0.78],'LineWidth',2)
plot(tm,ym,'o','MarkerSize',5,'Color',[0.48 0.06 0.89],'MarkerFaceColor',[0.48
0.06 0.89])
lg1 = legend({'real','estimado'},1,'EdgeColor',[1 1 1]);
axis([0 20 0 8])
set(gca,'XTick',[0:5:20])
set(gca,'YTick',[0:2:8])
set(gca,'Fontsize',10)

Cmo calcular el coeficiente de determinacin


Una vez que hemos ajustado una serie de puntos con una determinada funcin,
se suele utilizar el coeficiente de determinacin (R 2) para medir lo bueno/malo
que es el ajuste. Cuanto R2 ms se aproxime a 1, el ajuste ser mejor. Existen

varias definiciones de R2, pero quizs la ms popular sea la siguiente:


R2 = 1 - SSerror/SStotal
donde:
SSerror = (ymedido (i) - ycalculado (i))2
SStotal = (ymedido (i) - ymedido medio)2
Para crear una funcin que calcule R 2, creamos el siguiente funcin "fR2.m":
function z = fR2(ym,ycal)
yav = mean(ym);
s1 = sum((ym-yav).^2);
s2 = sum((ym-ycal).^2);
z = 1 - s2/s1;
Por ejemplo, tenemos el conjunto de puntos siguientes:
x = [1 2 3 4 5]';
ym = [1.24 0.59 0.31 0.19 0.09]';
que hemos ajustado a la ecuacin y=2.4exp(-0.69x).
El calculo de R2 se hace directamente:
ycal = 2.4*exp(-0.69*x);
R2 = fR2(ym,ycal)
Matlab nos devuelve el valor 0.9963, que corresponde con un ajuste muy
bueno.
Cmo calcular el mnimo de una funcin sin restricciones
Resolver un problema NLP en Matlab es muy sencillo. Por ejemplo, vamos a
calcular el mnimo de la funcin de Rosenbrock:

z = (1-x)2 + 100(y-x2)2

En primer lugar, definimos la funcin a minimizar en un archivo .m ("f01.m"):


function z = f01(u)
x = u(1);
y = u(2);
z = (1-x).^2 + 100*(y-x.^2).^2;
A continuacin, usamos la funcin "fminsearch" para encontrar la solucin.
La funcin fminsearch se utiliza para encontrar la solucin a un problema NLP
sin restricciones. Por ejemplo, en este caso, escribimos:
[u,f] = fminsearch(@(u) f01(u),[0 0])
donde u son los valores de "x" e "y" que minimizan la funcin, mientras que "f"
es el valor de la funcin en ese punto. [0 0] es un vector con los valores
iniciales de "x" e "y", con los que Matlab empezar a buscar la solucin.

Matlab nos devuelve lo siguiente:

u=
1.0000

1.0000

f=
3.6862e-010

En el caso de que queramos utilizar lmites superior e inferior para las


variables, podemos usar la funcin "fmincon". Por ejemplo, si tenemos los
siguientes lmites en las variables:

2.0 < x > 1.1


0.8 < y < 2.2

Calculamos directamente el mnimo como:


u0 = [0 0]; % valores iniciales
umin = [1.1 0.8]; % valores minimos
umax = [2.0 2.2]; % valores maximos
[u, f] = fmincon(@(u) f01(u),u0,[],[],[],[],umin,umax)
Matlab nos devuelve los siguientes valores:
u=
1.1000

1.2100

f=
0.0100

Cmo calcular el mnimo de una funcin con restricciones


La funcin "fmincon" se utiliza para resolver problemas de este tipo:
calcular x, minimizando fun(x)
sujeto a las siguientes restricciones:

g(x) <= 0

geq(x) = 0

Ax - B <= 0

Cx - D = 0

xmin <= x <= xmax

Dicha funcin se utiliza de las siguientes maneras:

fmincon(@(x) fun(x), x0, A,B)

fmincon(@(x) fun(x), x0, A,B,C,D,xmin,xmax)

fmincon(@(x) fun(x), x0, A,B,C,D,xmin,xmax,@(x) funrest(x))

donde:

x0 es el valor inicial a partir del que Matlab empieza a tantear.

Si uno de los parmetros no existe, se pone [].

fun(x) es la funcin a optimizar, y devuelve un escalar.

las restricciones lineales se aaden con las matrices A, B, C y D.

las restricciones no lineales se escriben dentro de una funcin


("funrest(x)"), que devuelve dos dos vectores, g(x) y geq(x). (El tamao
de los dos vectores corresponde con el nmero de restricciones de tipo
"menor o igual que" e "igual que".)

Por ejemplo, queremos optimizar la funcin de Rosenbrock siguiente:


z = (1-x)2 + 2(y-x2)2
teniendo en cuenta las siguientes restricciones lineales:

y + x -1 <= 0

-y -1/3x - 2/3 <= 0

y las siguientes restricciones no lineales:

y + 0.94x2 - 0.14x -3 <= 0

-y +0.143x2 - 1.03 <= 0

Primero, creamos el fichero "f01.m" con la funcin a minimizar:


function z = f01(u)
x = u(1);
y = u(2);
z = (1-x).^2 + 2*(y-x.^2).^2;

A continuacin, creamos el fichero "frest01.m" con las restricciones no lineales.


function [z zz] = fc01(x)
z(1) = x(2)+0.9375*x(1).^2-0.125*x(1)-3;
z(2) = -x(2)+0.1333*x(1).^2-1.0333;
zz = [];
En este caso, "z" son las restricciones de tipo "menor o igual que", mientras
que "zz" son las restricciones de tipo "igual que". Como en este ejemplo, no
hay restricciones del segundo tipo, la salida de "zz" es el conjunto vaco.

El mnimo de la funcin de Rosenbrock est en (1,1). En la siguiente figura se


pueden ver las isolneas de dicha funcin.

Para representar la anterior figura, lo hice con las siguientes lneas:


x = [-2:0.1:2];
y = [-1:0.1:3];
nx = length(x);

ny = length(y);
[X,Y] = meshgrid(x,y);
Z = zeros(nx,ny);
for i=1:1:nx
for j=1:1:ny
Z(i,j) = f01([X(i,j),Y(i,j)]);
end
end
[u,f] = fminsearch(@(u) f01(u),[0 0]);
figure(1)
hold on
contour(X,Y,Z,[75])
plot(u(1),u(2),'+k')
set(gca,'XTick',[-2:1:2])
set(gca,'YTick',[-1:1:3])
set(gca,'Fontsize',10)
axis([-2 2 -1 3])
box on

A continuacin, represento el rea permitida a partir de las restricciones del


ejemplo. Como se ve, el punto (1,1) est fuera de este rea.

Para representar el rea permitida, lo hice con las siguientes lneas:


t = linspace(-1.7476,-0.9785,100)';
r = -0.9375*t.^2+0.125*t+3;
plot(t,r,'-','LineWidth',2,'Color',[0 0 0])
t = linspace(0.8262,1.6639,100)';
r = 0.1333*t.^2-1.0333;
plot(t,r,'-','LineWidth',2,'Color',[0 0 0])
t = linspace(-0.9785,1.6639,100)';
r = 1-t;
plot(t,r,'-','LineWidth',2,'Color',[0 0 0])
t = linspace(-1.7476,0.8262,100)';
r = -1/3*t-2/3;
plot(t,r,'-','LineWidth',2,'Color',[0 0 0])
x(2)+0.9375*x(1).^2-0.125*x(1)-3;

A continuacin, resolvemos el problema de optimizacin con la funcin


"fmincon", como muestro a continuacin:
A = [1 1; -1/3 -1];
B = [1; 2/3];
[xs,fs] = fmincon(@(u) f01(u), [0,0],A,B,[],[],[],[],@(u) frest01(u))
Matlab devuelve la solucin:
xs =
0.6512

0.3488

fs =
0.1330
Finalmente, representamos la solucin del problema en el grfico:
plot(xs(1),xs(2),'o','MarkerSize',10,'Color',[1 0 0],'LineWidth',2)

Por ltimo, vamos a aadir la siguiente restriccin de igualdad no lineal.

y - (0.08x3 + 0.4x2 - 0.4x - 1.2)(x+2 )-1 = 0

Es decir, la solucin debe encontrarse, sobre dicha curva.


t = (-2:0.05:2)';
r = (0.08*t.^3+0.4*t.^2-0.4*t-1.2)./(t+2);
plot(t,r,'-','LineWidth',2,'Color',[1 0 0])

Para ello, lo nico que tenemos que hacer es modificar el archivo con las
restricciones no lineales ("frest01"), como muestro a continuacin:
function [z zz] = frest01(x)

z(1) = x(2)+0.9375*x(1).^2-0.125*x(1)-3;
z(2) = -x(2)+0.1333*x(1).^2-1.0333;

zz = x(2) - (0.08*x(1).^3+0.4*x(1).^2-0.4*x(1)-1.2)./(x(1)+2);

Finalmente, calculamos la nueva solucin:

[xs,fs] = fmincon(@(u) f01(u), [0,0],A,B,[],[],[],[],@(u) frest01(u))


plot(xs(1),xs(2),'o','MarkerSize',10,'Color',[0 0 0],'LineWidth',2)

Matlab calcula los siguientes valores:

xs =

0.3428 -0.5493

fs =

1.3212

Cmo cambiar la frecuencia de un vector


Hemos calculado la variable "y1" con una cierta frecuencia. Y conocemos el
valor de "y1" en los instantes de tiempo definidos en otro vector "t1". Por
ejemplo, en este caso, "t1" vara de 0.1 en 0.1, desde 0 hasta 10 segundos.

t1 = [0:0.1:10]';
y1 = sin(t1*2*3.1416/20);
Ahora, queremos seleccionar los datos de "y1", en otra frecuencia distinta,
definida por los instantes de tiempo dados en el vector "t2". Por ejemplo, el
siguiente:
t2 = linspace(1,9,7)';

Nota: La funcin linspace(x1,x2,n) genera n puntos equidistantes, entre x1 y


x2. En este caso, "t2" son 7 puntos equidistantes, entre 1 y 9. Es decir, 1.00,
2.33, 3.67, 5.00, 6.33, 7.67, 9.00.

Para ello, bastara usar las siguientes lneas:


y2 = resample(timeseries(y1,t1),t2);
y2 = y2.data;
Por ltimo, representamos los valores de "y1" e "y2".
figure(1)
hold on
box on
plot(t1,y1,'-b')
plot(t2,y2,'or')

Cmo transformar un nmero o un array en un string


Muchas veces queremos aadir en el texto de un grfico (en el ttulo, en los
ejes, en la leyenda...) el valor de una variable. Para hacer esto, necesitamos
transformar la variable de tipo numrico, a tipo string. Esto se puede hacer con
la funcin "mat2str", como muestro a continuacin:

r = [2, 3];
z1 = ['Hay ' mat2str(r(1)) ' monstruos en el armario']
Hay 2 monstruos en el armario

Nota: Los strings se crean encerrando el texto entre apstrofes: 'texto'. Con
mat2str creamos otro string. Por ltimo, fusionamos los strings con los
corchetes.

Si trabajamos con arrays, es muy parecido. Ahora, habra que transformar la


variable de tipo array, a tipo matemtico, con la funcin "cell2mat". Por
ejemplo, si tenemos el siguiente array:
R = {'10', 15};
El primer elemento es un string, y el segundo un escalar. Pero cuando hacemos
R(1) o R(2), ambas variables siguen siendo del tipo array. Con "cell2mat", los
transformamos en variables de tipo string y numrico. Por ltimo, R(2) hay que
transformarlo en string, con "mat2str":
z2 = ['Hay ' cell2mat(R(1)) ' caimanes bajo la cama']
z3 = ['Hay ' mat2str(cell2mat(R(2))) ' fantasmas en la sala']
Hay 10 caimanes bajo la cama
Hay 15 fantasmas en la sala
Cmo salvar variables en Matlab
Si queremos salvar varias variables, en un fichero, podemos usar el comando
"save". Por ejemplo:
A = magic(3);
q = 23;
t = 'Hola';
save data1.mat A q t

Tambin podemos salvar las variables en un fichero de texto, para poder ser
abierto fcilmente con otros programas:
save data1.txt -ascii A

Una forma alternativa, sera utilizando una estructura. El resultado es el mismo.


M.A = A;
M.q = q;
M.t = t;
save('data2.mat','-struct','M')

Para cargar los datos, bastara utilizar el comando "load":


clear all
load data1.mat
load ('./carpeta1/data1.mat')
Cmo cargar datos desde un fichero de texto
La funcin "importdata" nos permite cargar datos de un fichero de texto.

Por ejemplo, si queremos cargar un fichero de texto llamado "data.txt", que


consistiera en los siguientes datos:
8
3
4

1
5
9

6
7
2

Haramos:
A = importdata('data.txt')

Si el fichero de texto tuviera texto y nmeros, como el siguiente

matriz magica
8
1
3
5
4
9

6
7
2

Al cargar los datos desde Matlab, nos estara creando una estructura. Para
acceder a los datos y al texto, podramos hacer:
A = importdata('data.txt')
B = A.data
t1 = cell2mat(A.textdata)
clear A
B sera la matriz de datos, mientras t1 sera un string con la frase "matriz
magica".
Cmo salvar lo que estamos haciendo en un fichero de texto
La funcin "diary" nos permite salvar, en un fichero de texto, lo que aparezca
por pantalla. Por ejemplo, el siguiente cdigo:
diary('diario1.txt')
x=3
A = 10000;
diary of
generara un fichero de texto, llamado "diario1.txt", de la siguiente forma:

Fjate que la variable A, al no aparecer por pantalla, no aparece en el fichero.

Si vuelvo a ejecutar el programa varias veces, Matlab escribe a continuacin de


lo ya escrito en el fichero de text. Es decir, hara lo siguiente:

Si queremos que cada vez que se ejecute el programa, se borre lo que haba
inicialmente en el fichero de texto, habra que aadir la lnea siguiente:
delete('diario1.txt')
diary('diario1.txt')
x=3
diary of

Por ltimo, un ejemplo de cmo crear n archivos, con un bucle for.


nombre = {'diario'};
n = 3;
for i=1:1:n
delete([cell2mat(nombre(1)) mat2str(i) '.txt'])
diary([cell2mat(nombre(1)) mat2str(i) '.txt'])

x=i
diary of
end

Funciones con nmeros


En la siguiente entrada, resumo algunas funciones importantes cuando
estamos trabajando con nmeros.

Nmeros primos.
o

isprime(x) nos dice si un nmero es primo (respuesta 1), o


compuesto (respuesta 0).

factor(x) nos da los factores de un nmero compuesto.

Nmeros complejos
o

real(x) nos calcula la parte real de x.

imag(x) nos calcula la parte imaginaria.

conj(x) nos devuelve el conjugado.

Nmeros enteros.
o

round(x) nos redondea un nmero al entero ms prximo.

floor(x) nos redondea un nmero al entero inferior.

ceil(x) nos redondea un nmero al entero superior

x = [2.1,-2.1]
round(x)
nos devuelve
floor(x)
nos devuelve
ceil(x)
nos devuelve

2
2
3

-2
-3
-2

Divisiones.
o

Por ejemplo, en la fraccin 11/4, el cociente es 2, y el resto es 3.


(11 = 42 + 3)

El resto lo podemos calcular con rem(11,4) = 3

Y el cociente con floor(11/4) = 2

Nmeros aleatorios.
o

rand
abierto (0,1)

nos calcula un nmero aleatorio en el conjunto

rand(n1,n2)

nos cacula una matriz de nmeros aleatorios n1xn2

rand(n)

nos cacula una matriz de nmeros aleatorios nxn

Nmeros aleatorios entre (a,b).


o

rand*(b-a) + a

un solo nmero.

rand(n,1)*(b-a) + a un vector columna de n elementos.

Nmeros aleatorios enteros entre [a,b]. (incluyendo a y b).


o

floor(rand*(b+1-a)+a)

un solo nmero.

floor(rand(n,1)*(b+1-a)+a) un vector columna de n elementos.

También podría gustarte