Mi blog personal sobre investigación y divulgación
Tag Archives: MATLAB
De MATLAB a R

Desde hace muchos años trabajo en MATLAB. Comencé en IDL, que es muy similar, pero luego fue necesario adaptarme al lenguaje de programación que usaban (y usan cada vez menos) en el que por aquel entonces era mi nuevo centro de trabajo.

MATLAB es un entorno muy potente para trabajar con grandes cantidades de datos. Puede usarse en Windows, Mac y Linux, aunque en alguna ocasión me he encontrado con alguna pequeña diferencia en las versiones de Windows y Mac, teniendo que hacer pequeñas adaptaciones a scripts que ya tenía hechos. En este blog he escrito varias entradas relacionadas con MATLAB, y hasta ahora no había sentido la necesidad de cambiar de lenguaje de programación (si es que a estos paquetes estadísticos donde trabajamos con scripts se le puede llamar “lenguaje de programación”). El caso es que MATLAB, frente a sus competidores, tiene algunas desventajas muy llamativas que me han invitado a probar con otros. La gran desventaja es que es de pago, con un precio muy elevado, mientras que otros como OCTAVE o R son gratuitos. Por otro lado, y esto puede ser ya cuestión de gustos personales, las gráficas y mapas que se generan con MATLAB me parecen horrendas. Otra desventaja es que puedes necesitar una toolbox en MATLAB que no tienes instalada, o que no existe en la versión que tú estás utilizando, y entonces empiezan los problemas. Un detalle más: guardar una gráfica de MATLAB como fichero gráfico no es más que esperar a que el propio programa haga una captura de pantalla, por lo que esa captura depende de la configuración de tu tarjeta de vídeo + pantalla. Generar una misma gráfica (o un mapa) con el mismo script pero en dos ordenadores distintos puede dar resultados diferentes. Eso me parece una chapuza.

Tomar una decisión sobre qué otro lenguaje usar no fue difícil, pues la tentación estaba muy cerca. Algunos de mis colegas ya se habían pasado hace tiempo a R. Me gusta el resultado de las salidas gráficas que consiguen. La sintaxis de este lenguaje no parece muy difícil si ya se está familiarizado con otros lenguajes. Además, es gratis, multiplataforma, y hay una gran comunidad de usuarios en internet. Traducir mis scripts de MATLAB a R me parece una pérdida de tiempo, pero tener que abordar un problema nuevo sí es una buena excusa para empezar en R. Este es el caso y por fin lo he instalado y estoy tratando de correr mis primeros programas. También instalé un IDE, el RStudio (también gratis y multiplataforma), para que el entorno me sea un poco más familiar y contar con unas cuantas funcionalidades interesantes.

R Studio

Pues eso, de la directora de “Me olvido de Windos y me paso a Linux” llega la nueva entrega “De MATLAB a R”. ¡A ver en qué termina la película! 🙂

Identificar con MATLAB valores repetidos en un vector

En el contexto de muchos estudios que podamos estar haciendo con una serie de datos, un problema típico que no encontramos es el de necesitar identificar valores duplicados en un vector. Por ejemplo, puedes necesitar simplemente identificar un registro que por alguna razón se haya escrito dos veces en la base de datos.

Si trabajas con MATLAB seguramente sabrás que hay un comando para identificar valores únicos dentro de un vector (el comando unique), pero hasta donde yo sé no hay uno para identificar valores que están repetidos. Claro, la lógica nos dice que si podemos cuáles son únicos ya tenemos el problema resuelto, porque todos los demás aparecerán en el vector al menos dos veces. El problema es, por un lado, saber cuáles son esos valores y, por otro lado, logran conocer el índice que nos indica la posición de esos valores en el vector. Con esta información podríamos, por ejemplo, construir un nuevo vector que nos sirva de flag para solo marcar los valores repetidos.

Yo me encontré con este problema y lo primero que hice fue lo obvio…programar un loop donde se calculara la diferencia de un valor con el anterior, y si la diferencia era nula entonces ya tenía localizado un valor que se repetía. El problema es que en mi caso esa era una información muy limitada, porque los valores repetidos no tenían por qué aparecer uno después del otro en la base de datos.

Hay varias maneras (similares) de resolver esto, pero yo voy a mostrar aquí la que me resultó más sencilla. Supongamos que nuestro vector, que contiene algunos valores repetidos, es el que llamamos “vector”.

Lo primero que hago es identificar los valores únicos (los que nunca se repiten) y sus posiciones en el vector:

[valores_unicos, ind_unicos] = unique(vector);

Luego identifico los índices que me marcan las posiciones de los valores que sí están repetidos. Para ello hago uso del comando setdiff:

ind_repetidos = setdiff(1:length(vector), ind_unicos);

Ahora extraemos los valores de esos registros repetidos:

valores_repetidos = vector(ind_repetidos, 1);

Pero claro, si quiero construir otro vector que me sirva de flag para indicar los datos repetidos, que aparecen dos o más veces, tengo que identificar dónde están esos valores todas las veces que se repitan. Esto puede parecer lioso, pero imagina que tenemos un vector que es [2 2 2 3 4 5]. Con lo anterior lo que hacemos es identificar que el valor repetido es 2 y que ese 2 aparece por primera vez en la posición 1 del vector. Yo lo que estoy buscando es tener un vector que sea [1 1 1 0 0 0], es decir, que me marque con un 1 todos los sitios donde aparezca un valor que aparezca al menos dos veces.

Para ello el siguiente paso es este, donde uso el comando ismember. Lo que hago es pedirle a MATLAB que busque en mi vector cuáles son los índices (posiciones en el vector) donde se encuentra cualquiera de los valores repetidos.

ind_flag=ismember(vector, valores_repetidos);

ind_flag es ya el vector que estamos buscando, el que nos indica con un 1 un valor que está repetido, y con un cero los valores únicos. Para conocer el número de datos repetidos simplemente buscamos en ind_flag todos los valores diferentes de cero (o mayores que cero, o iguales a 1, como prefieras).

numero_repetidos=length(find(ind_flag >0));

Si quieres grabar el vector ind_flag en un fichero de texto, por ejemplo para importarlo en MATLAB en otra sesión de trabajo, o para importarlo en una hoja de cálculo Excel o similar, podrías usar este código:

fid=fopen(‘flag.txt’,’wt’);
formato=’%d\n’;
for i=1:size(ind_flag,1);
fprintf(fid,formato,ind_flag(i,:));
end
fclose(fid)

Y con esto ya tienes el método, que puedes reducir a los cuatro primeros pasos, para identificar todos los valores que aparecen iguales más de una vez en un vector, e incluso crear un nuevo vector para identificar dónde están esos valores.

Libro recomendado (enlace afiliado):


Guardar una matriz formateada en un archivo de texto en MATLAB

Este post debería en realidad llamarse algo así como “Cómo guardar una matriz con formato en un archivo de texto con MATLAB, y no morir en el intento”.

Es muy posible que si usas MATLAB y tienes un set de datos guardados en una matriz, quieras guardar esa matriz en un fichero de texto. Esto puede servirte para cargarlos en MATLAB posteriormente, o usarlos con otro programa como puede ser Excel. Hay muchas maneras de hacer esto, pero cuando queremos guardar cada columna con un determinado formato la cosa se complica un poco. Se complica porque hay que empezar a lidiar, por un lado, con la definición del formato y, por otro lado, con las formas aveces poco lógicas de trabajar en MATLAB. Que sí, que es un software fantástico, pero aveces tiene detalles y caprichos que dan ganas de tirar la toalla con él.

Una de las formas de guardar nuestra matriz de datos en MATLAB es usar el comando fprintf. Con pfrintf puedes especificar el formato con el que quieres escribir cada columna de la matriz (puede que una columna sea un número con 4 decimales, otra sea un número entero, otra sea una cadena de texto…). Las normas para aplicar el formato deseado son las que encontrarás aquí. El caso es que, una vez escrito el formato, podrías encontrarte con una desagradable sorpresa como me ha pasado a mí, y es que siguiendo el típico ejemplo que Mathworks escribe en web o en la ayuda de MATLAB, solo consigues escribir valores de la primera columna pero ordenados en filas hasta que se acaban y comienzan a escribirse valores de la segunda columna y así sucesivamente. Voy a poner un ejemplo para que se entienda mejor lo que quiero decir:

Supongamos que tenemos un set de datos que consta de 4 columnas con 4 filas. La primera columna es temperatura dada con un decimal, la segunda es año, la tercera es mes y la cuarta es día (en estas tres últimas columnas todos los valores son enteros). Entonces, nuestra definición de formato sería algo así: formato=’%5.2f %d %d %d\n’    Tenemos 4 filas, lo que quiere decir que lo que queremos guardar es un registro de cuatro medidas de temperatura con su correspondiente fecha. Podría ser algo así:

temperatura=[10.25; 40.36; 28.50; 3.32]

agno=[2003; 2003; 2003; 2003]

mes=[12; 12; 12; 12]

dia=[25; 25; 25; 25]

datos=[temperatura, agno, mes, dia]

Muy bien, pues es muy posible que para grabar este set en un fichero y con el formato que queremos probemos con esto:

formato=’%5.2f %d %d %d\n’

fid=fopen(‘ficherodatos.txt’,’w’);

fprintf(fid,formato,datos);

fclose(fid);

————–

La \n es para empezar a escribir en una nueva línea tras escribir los primeros valores de cada columna. %d es para escribir números enteros, y el %5.2f lo hemos puesto para escribir la temperatura con dos decimalos. El 5 en %5.2 significa que pueden haber 5 caracteres de texto en total, contando la parte entera, el punto y los dos decimales.

La desagradable sorpresa es que fichero de texto que se ha grabado tiene esta pinta:

Fichero de texto MATLAB

Como ves, ha escrito cuatro columnas pero con los valores de la temperatura primero, luego los años, luego mes y finalmente día, eso sí, con el formato que le pedimos. Pero no es el orden en el que queremos los datos!

La solución es escribir un pequeño código con un sencillo loop, como este:

fid=fopen(‘ficherodatos.txt’,‘wt’);

formato=’%5.2f %d %d %d\n’ ;

for i=1:size(datos,1);

    fprintf(fid,formato,datos(i,:));

end

fclose(fid)

Ahora sí, si abrimos el fichero de texto resultante nos encontramos con esto:

Archivo de texto MATLAB

Esto sí es justo lo que queríamos. En el código de arriba verás que en la instrucción fid he puesto ‘wt’ en vez del ‘w’ que teníamos al principio. Esto es para indicarle que queremos escribir en un fichero que es un fichero de texto y que debe adaptarse a las directrices seguidas por los ficheros de texto en el sistema operativo donde estés ejecutando este código. Esto puede interesarte o no. Lo que he hecho es comprobar cuáles son las dimensiones de la matriz datos y hacer un loop desde 1 hasta el número de datos en cada columna (esto es, el número de filas). Dentro del loop he ordenado a MATLAB que escriba las filas de la matriz datos, una a una, en el archivo ficherodatos.txt con el formato deseado.

Ahí queda este tip por si lo necesitas en algún momento. A mí además me sirve escribirlo aquí para no perder estos apuntes entre cientos de papeles. 🙂

Cómo repetir elementos de un vector en MATLAB

Hoy descubrí una función de MATLAB hasta ahora desconocida para mí, llamada kron. El descubrimiento surgió de la necesidad de solucionar este aparentemente sencillo problema: ¿cómo repetir n veces cada uno de los elementos de un vector, de manera que se repita el primer valor, luego el segundo, y así sucesivamente?

Para verlo más claro, veámoslo con números. Supongamos que tengo un vector cuyos elementos son 1, 2, 3, 4 y 5,  y lo que quiero conseguir es un vector cuyos elementos son 1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5. Es decir, quiero repetir 4 veces cada uno de los elementos.

Para hacer esto sin necesidad de programar un bucle con un clásico for, podemos usar la función kron de esta manera:

kron(x, ones(n,1))

En el caso del ejemplo que puse arriba, habría que escribir:

>> nuestrovector=[1,2,3,4,5]

> resultado=kron(nuestrovector, ones(4,1))

>> resultadofinal=reshape(resultado,1,size(resultado,1)*size(resultado,2))

Y entonces resultado sería nuestro nuevo vector donde ya tenemos los elementos repetidos.

Kron, viene del producto de Kronecker (aquí puedes ver la documentación de Mathworks sobre esta función de MATLAB) que podemos aprovechar para solucionar nuestro problema.


Cómo cambiar el tamaño de símbolo en una leyenda de MATLAB

Llevo unos días tratando de resolver un problema aparentemente muy tonto en una gráfica hecha con MATLAB, pero por mucho que he estado buscando en la ayuda del programa y en internet, no daba con la solución. El problema es el siguiente: representas una serie de datos en una gráfica y añades a la gráfica una leyenda, pero quieres que los símbolos de las leyendas aparezcan en un tamaño más grande que el que tienen por defecto. Parece una tontería, pero por lo visto MATLAB no permite modificar el tamaño de los símbolos de la leyenda de una forma tan intuitiva como lo permite hacer para los símbolos en la propia gráfica.

Voy a poner un ejemplo visual. Esta es una gráfica del tipo scatterm, es decir, una serie de puntos localizados en las coordenadas x e y a los que les asignamos valores. El dimátero del círculo varía con ese valor.

plot1

En la leyenda, arriba a la derecha, puedes ver que el punto al lado de la palabra “data1” es muy pequeño, quizás extremadamente pequeño para incluirlo en una figura para publicar o añadir a una presentación. Pues bien, después de leer mucho y juntar varias posibles soluciones, esta es la solución a la que llegué para hacer esto en la versión R2010a de MATLAB (y creo que funciona desde esa versión en adelante):

– Una vez representada la gráfica, escribe esto en la ventada de comandos

I=findobj(gcf,'tag','legend');
a=get(I,'Children');
set(get(a(1),'Children'),'markersize',20);

El número que está señalado en rojo es el que debes cambiar hasta conseguir el tamaño que quieras. Con un valor de 20, yo conseguí este resultado:

plot2

La propiedad ‘markersize’ de las leyendas parece ser que se podía cambiar más fácilmente en versiones anteriores de MATLAB, pero si tratas de hacerlo como indican algunos usuarios en diferentes foros de la red te encontrarás con el error ‘there is no ‘MarkerSize’ property in the ‘hggroup’ class’. De esta otra manera que te propongo aquí sí te debería funcionar.

En el caso de que tengas muchos símbolos en la leyenda, tienes que tener en cuenta que tanto símbolos como textos de la leyenda se guardan en la variable que hemos llamado “a”. Si tienes un segundo símbolo, puedes hacer lo mismo que antes pero con a(3) y verás que ese símbolo también cambia de tamaño. Jugando un poco con esto conseguirás que los símbolos de las leyendas sean bien visibles.

Espero que este truco te sirva en tus trabajos. Yo lo estoy usando con mapas de este tipo pero referenciados a coordenadas de latitud y longitud, sobre un mapa geográfico (es algo que no puedo hacer con Veusz), y ahora sí que quedan bien las leyendas.

ACTUALIZACIÓN: Misterios de la informática….al grabar la figura a un archivo gráfico (tanto en jpg, como en tiff, eps, etc.) encuentro que el cambio en el tamaño del símbolo de la leyenda desaparece. Esto no ocurre en todas las figuras pero en algunas de las que tengo ya hechas sí que ocurre. La solución está en ir al Export Setup dentro de el menú File de la figura, seleccionar Rendering y allí activar Custom Renderer (a mí me funciona con painters (vector format) en el menú desplegable), luego aplicar a la figura y luego OK. Ahora el cambio sí se verá reflejado cuando grabes la figura en un fichero gráfico.