miércoles, 2 de julio de 2014

Sobre este blog

Este no es un blog para aprender Matlab. Pero sí recopila algunas funciones y comandos útiles. A continuación puedes ver los contenidos del blog. Quizás alguna entrada te pueda ser útil. :-)

Gráficos:
  • Ideas generales para hacer gráficos en 2 dimensiones (click aquí).
  • Para añadir un eje secundario (click aquí).
  • Para dibujar círculos y polígonos (click aquí).
  • Para rotar o trasladar una curva (click aquí).
  • Para hacer un gráfico en coordenadas polares (click aquí).
  • Ideas generales para hacer gráficos en 3 dimensiones (click aquí).
  • Para representar una matriz de colores en 3 dimensiones (click aquí).

Optimización y Estimación de Parámetros:
  • Para ajustar un polinomio a unos puntos (click aquí). 
  • Para realizar la estimación de parámetros de una función (click aquí).  
  • Para realizar la estimación de parámetros, usando Simulink (click aquí).  
  • Para calcular el coeficiente de determinación (R2) (click aquí).
  • Optimización sin restricciones (click aquí).
  • Optimización con restricciones (click aquí).

Otras cosas:
  • Para cambiar la fruencia de un vector (click aquí).
  • Para transformar una variable de tipo string en número (click aquí).
  • Para salvar datos en Matlab (click aquí).
  • Para cargar datos de un fichero de texto (click aquí).
  • Para salvar nuestro trabajo en un fichero de texto (click aquí).
  • Funciones con números enteros, complejos, aleatorios... (click aquí).
     

Funciones con números

En la siguiente entrada, resumo algunas funciones importantes cuando estamos trabajando con números.
  • Números primos.
    • isprime(x) nos  dice si un número es primo (respuesta 1), o compuesto (respuesta 0).
    • factor(x) nos da los factores de un número compuesto. 

  • Números complejos
    • real(x) nos calcula la parte real de x.
    • imag(x) nos calcula la parte imaginaria.
    • conj(x) nos devuelve el conjugado.

  • Números enteros.
    • round(x) nos redondea un número al entero más próximo.
    • floor(x) nos redondea un número al entero inferior.
    • ceil(x) nos redondea un número al entero superior
                 x = [2.1,-2.1]
                 round(x)      nos devuelve    2    -2
                 floor(x)        nos devuelve    2    -3
                 ceil(x)         nos devuelve    3    -2

  • Divisiones.
    • Por ejemplo, en la fracción 11/4, el cociente es 2, y el resto es 3. (11 = 4·2 + 3)
    • El resto lo podemos calcular con rem(11,4) = 3
    • Y el cociente con floor(11/4) = 2

  • Números aleatorios.
    • rand                nos calcula un número aleatorio en el conjunto abierto (0,1)
    • rand(n1,n2)    nos cacula una matriz de números aleatorios n1xn2
    • rand(n)           nos cacula una matriz de números aleatorios nxn

  • Números aleatorios entre (a,b).
    • rand*(b-a) + a           un solo número.
    • rand(n,1)*(b-a) + a   un vector columna de n elementos.

  • Números aleatorios enteros entre [a,b]. (incluyendo a y b).
    • floor(rand*(b+1-a)+a)          un solo número.
    • floor(rand(n,1)*(b+1-a)+a)   un vector columna de n elementos.

martes, 26 de noviembre de 2013

Cómo salvar lo que estamos haciendo en un fichero de texto

La función "diary" nos permite salvar, en un fichero de texto, lo que aparezca por pantalla. Por ejemplo, el siguiente código:

diary('diario1.txt')
x = 3
A = 10000;
diary off

generaría un fichero de texto, llamado "diario1.txt", de la siguiente forma:



Fíjate 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 continuación de lo ya escrito en el fichero de text. Es decir, haría lo siguiente:



Si queremos que cada vez que se ejecute el programa, se borre lo que había inicialmente en el fichero de texto, habría que añadir la línea siguiente:

delete('diario1.txt')
diary('diario1.txt')
x = 3
diary off



Por último, un ejemplo de cómo 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 off
end

Cómo 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 numérico. Es decir, quiero, de una matriz como la siguiente:

f1 1 2 3
f2 4 5 6

v1 v2 v3

llegar a algo como esto:




Para ello, podría 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 continuación, genero el gráfico 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 definía con "YTick". Si la barra hubiera estado horizontal, habría 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 botón "Rotate 3D", puedes elegir el punto de vista que más te guste. En este caso, sí que podríamos también 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'})

Cómo transformar un número o un array en un string

Muchas veces queremos añadir en el texto de un gráfico (en el título, en los ejes, en la leyenda...) el valor de una variable. Para hacer esto, necesitamos transformar la variable de tipo numérico, a tipo string. Esto se puede hacer con la función "mat2str", como muestro a continuación:

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 apóstrofes: 'texto'. Con mat2str creamos otro string. Por último, fusionamos los strings con los corchetes.



Si trabajamos con arrays, es muy parecido. Ahora, habría que transformar la variable de tipo array, a tipo matemático, con la función "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 numérico. 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

jueves, 21 de noviembre de 2013

Cómo cargar datos desde un fichero de texto

La función "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           1           6
           3           5           7
           4           9           2

Haríamos:

A = importdata('data.txt')



Si el fichero de texto tuviera texto y números, como el siguiente

matriz magica
           8           1           6
           3           5           7
           4           9           2

Al cargar los datos desde Matlab, nos estaría creando una estructura. Para acceder a los datos y al texto, podríamos hacer:

A = importdata('data.txt')
B = A.data
t1 = cell2mat(A.textdata)
clear A

B sería la matriz de datos, mientras t1 sería un string con la frase "matriz magica".

miércoles, 20 de noviembre de 2013

Cómo 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

También podemos salvar las variables en un fichero de texto, para poder ser abierto fácilmente con otros programas:

save data1.txt -ascii A



Una forma alternativa, sería 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, bastaría utilizar el comando "load":

clear all
load data1.mat
load ('./carpeta1/data1.mat')

jueves, 31 de octubre de 2013

Cómo 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" varía 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 función 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, bastaría usar las siguientes líneas:

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')

miércoles, 19 de enero de 2011

Cómo añadir un eje secundario en un gráfico

A veces resulta interesante representar en un mismo gráfico dos curvas distintas. Si estas curvas tienen distintas unidades o se mueven en un distinto rango, habría que trabajar con dos ejes distintos. Esto se puede hacer fácilmente con la función "plotyy". Sin embargo, si queremos editar los ejes, es un poco más complejo. En esta entrada, muestro cómo 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 continuación, represento las dos curvas con el siguiente código:

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 escribiría dos veces, uno sobre el otro, y quedaría un poco feo.

miércoles, 10 de noviembre de 2010

Opciones más importantes en un gráfico de 2 dimensiones

En la siguiente entrada resumo algunas de las opciones más importantes, a la hora de editar un gráfico.

Como ejemplo, vamos a representar la curva siguente:

y = A·sin(τ·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 gráfico 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 números de cada eje (x en este caso). En vez de números, 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 símbolos matemáticos se pueden poner con los mismos comandos de LaTeX (como se ve en el título).

- El número "2" en la leyenda, corresponde al segundo cuadrante. Se puede poner 1, 2, 3 o 4.

- Se puede elegir entre varios tipos de línea 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 tamaño, 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, además 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 cómo representar varias curvas distintas, usando un bucle for. Fíjate, cómo 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.