Saltar al contenido

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 identificar 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):

Publicado enDivulgación

32 comentarios

  1. José José

    Estimada Silvia,

    Hace poco empecé con la programación en Matlab, y estaba buscando una solución a una situación que se me había planteado y quería preguntarte si estás alternativas son aplicables a una variación más grande de datos, por ejemplo: si quiero encontrar la repetición de un vector [2 4 6 1 5 8 9], dentro de otro más grande. Es posible utilizar los comandos que vos recomendas? para un vector de ese tipo.

    Saludos y gracias

    • Hola José. Sí, creo deberían servirte los mismos comandos. Otra opción (seguro que hay más!) sería hacer un cálculo de este tipo en tu vector (supongamos que el vector grande se llama v):

      v_flag=zeros(size(v,2)); % Creo un vector que contiene solo ceros para usarlo como vector de flags
      for n=1:size(v,2);
      if v(n)==2 && v(n+1)==4 && v(n+2)==6 && v(n+3)==1 && v(n+4)==5 && v(n+5)==8 && v(n+6)==9 ;
      v_flag(n)==1 && v_flag(n+1)==1 && v_flag(n+2)==1 && v_flag(n+3)==1 && v_flag(n+4)==1 && v_flag(n+5)==1 && v_flag(n+6)==1 ; asigno un uno a los elementos del vector donde se encontraría la secuencia 2 4 6 1 5 8 9.
      else
      v_flag(n)==0 && v_flag(n+1)==0 && v_flag(n+2)==0 && v_flag(n+3)==0 && v_flag(n+4)==0 && v_flag(n+5)==0 && v_flag(n+6)==0;
      end
      end

      Si no me equivoco, así tendrías un vector v_flag donde te marcaría con un 1 las posiciones de v donde tendrías los elementos del vector repetido que estás buscando.

  2. Juan Martín Preciado Rodríguez Juan Martín Preciado Rodríguez

    Estimada Silvia, primero que gusto que te des tiempo para compartirnos tus conocimientos.
    Estoy buscando una función en Matlab que sea equivalente a la función which() de R. Se que puedo desarrollar la función, pero deseo tener un código más compacto. Te agradezco tu ayuda.

  3. Mayra Mayra

    Buenas tardes estoy comenzando a programar en matlab y no e podido lograr que alguna rutina me identifique las palabras repetidas que esten en una base de datos .txt alguien me podria ayudar se los agradezco.

    Atentamente.
    May 🙂

  4. Francisc Arcia Francisc Arcia

    Buenos Dias Silvia tengo una duda gigante, espero pueda ayudarme.
    Necesito comparar 2 vectores de diferente tamano un vector llamado Barras = [1 2 3 4 5 6 7 8 9 10 11 12 13 14] y otro vector llamado Medidas [2 3 4 5 6].
    Ahora bien para el vector barras cuando Barras (2) = 2 sea igual a Medidas (1) = 2 deseo que me imprima unos resultados «X» y cuando no que no imprima nada
    lo que he hecho es esto:
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    r = 1;
    x = 1;
    for nmt=1:length(MedTenbus1)

    if BarrasTension (r) =~ MedTenbus1 (x)

    x = x + 1;

    else

    MedTenbus (r) = MedTenbus1(x);
    Tenbus (r) = Tenbus1 (x); %Medidas de tension en Barras
    ValorTenW (r) = 1/St^2; %Valor del peso
    r = r + 1;
    x = x + 1;
    end

    end

    MedTenbus
    Tenbus
    ValorTenW
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    Deseo es comparar ambos vectores cuando sus numeros sean iguales imprimir y cuando no lo sean buscar un valor hasta que se repitan yo deberia imprimir solo los valores asociados al vector Medidas

    Espero que haya podido explicarme y que pueda ayudarme con esta gran duda.
    Saludos desde Venezuela.

    • Hola Francisco. Estoy tratando de ayudarte pero me he perdido con Tenbus1. No sé de dónde sale ese vector. ¿Me lo puedes aclarar y lo retomo a ver si podemos juntos dar con la solución? Saludos!

  5. yolman yasmany yela velasquez yolman yasmany yela velasquez

    Hola Silvia Saludos
    mi duda es la siguiente:
    Tengo un vector con 100 celdas
    en cada celdas hay numeros diferentes ordenados de menor a mayor( 1 es el mas pequeño y 10 el máximo
    entonces yo quiero que mi código diga
    cuantos calores de ese vector son menores a 1
    luego cuantos son menores a 2 y asi sucesivamente hasta 10
    y luego que me muestre el vector guardado donde dice por ejemplo cinco datos menores que 1
    7<2
    17<4
    asi
    gracias por tu ayuda muy amable

    • Hola. Para obtener el número de elementos menores que un número, lo más fácil sería usar la función count, así: conteo_menores = sum(vector(:) < x); donde en x debes poner 2, 3, 4, 5, ... 10 Como finalmente quieres guardar el resultado, yo haría for x=2:10 conteo_menores(x) = sum(vector(:) < x) end entonces en el vector conteo_menores tendrás el número de veces que encuentra elementos menores que un número, ordenado de 1 a 10. A este resultado si quieres puedes unirle otra columna de texto donde te indique lo que significa cada fila "menores que 2, menores que 3, menores que 4... Creo que así te debería funcionar. Saludos.

  6. Martín Carrillo Chávez Martín Carrillo Chávez

    Hola Silvia buenas Tardes estoy PROGRAMANDO EN MATLAB, mi duda es la siguiente. TENGO 1 VECTOR de caracteres
    vector_from = ‘V032’ ‘V037’ ‘V032’ ‘ V012’ ‘ V012’ ‘ V016′ V016′ V016′ V012’ ‘V032’ ‘V045’ ‘V037’ ‘V016’ ‘V032’ ‘V045’ ‘V052’ ‘CULC’ ‘CULC’ ‘CULC’ ‘CULC’ ‘CULC’ ‘CULC’ ‘CULC’ ‘CULC’

    con SUS RESPECTIVAS Posiciones o INDICES. La idea es asignarle un VALOR Numérico empezando EN 1 y donde SE REPITA EL CARACTER EN otra posición DEL VECTOR Ponerle el numero QUE YA SE Había asignado Anteriormente DE TAL Manera que debe DE QUEDAR ASI
    vector_from = 1 2 1 3 3 4 4 4 3 1 5 2 4 1 5 6 7
    CON inCREMENto de uno EN uno.
    agradecería MUCHÍSIMO SI ME PUDIERAS AYUDAR.

    SALUDOS Y GRACIAS.

    • Hola Martín. Es difícil porque son letras y números (strings), no números. Tendrías que trabajar con cells.

      No puedo probarlo en mi versión de matlab, porque esta opción no existe, pero creo que la clave para conseguir lo que buscas es esta:

      [C, ia, ic] = unique(vector_from,’stable’)

      La clave está en usar esa opción ‘stable’ y la solución será el vector ic

      Espero que te funcione. Saludos.

  7. Dinibel Dinibel

    Hola. Que buenos que están tus aportes, me he leído varios. Llevo dias tratando de hacer un programa que me haga lo siguiente:
    Tengo tres satélites (1,2,3), cada satélite ha medido 10 veces a un respectivo tiempo (t).
    Ahora bien, deseo colocar en la colocar en la columna 1 unos o ceros cuando los valores de t se repitan o no (respecto al satelite 2) en la columna 2 respecto al satelite 3.

    No se si me explico correctamente

    Gracias

    Dini

    • Hola Dini. Creo que entiendo lo que necesitas hacer. Tienes tres vectores (o una matriz con tres columnas que puedes separar en vectores), uno para cada satélite, que contienen las 10 medidas que hace cada uno. Quieres comparar estas medidas y, cuando el valor medido por el satélite 1 para un tiempo t coincide con la que mide el satélite 2 para ese mismo tiempo, quieres sustituir el valor de la medida del satélite 1 por un 1, y sustituir por un cero en el caso contrario. Lo mismo en la columna del satélite dos comparando con la del satélite 3.

      Creo que debería funcionarte con algo así:

      A = datos_satelite_a;
      B = datos_satelite_b;
      index_iguales=find(A==B);
      A(index_iguales)=1;
      A(A~=1)=0

      y creo que por aquí van los tiros. En el vector A tendrías ahora unos y ceros, unos donde el valor es igual al medido por el segundo satélite (al que he llamado b) y ceros en el resto.
      Tendrías que hacer lo mismo con los satélites b y c.

      Espero que esto te ayude. Saludos.

  8. Tony Castillo Tony Castillo

    Hola Profesora,
    Quiero hacer dos cosas en Matlab y aun no determino como hacerlo,
    Primero
    legend(‘Grupo 1′,’Grupo 2′,’Grupo 3′,’Grupo 4′,’Grupo 5′,’Grupo 6′,’Grupo 7’);
    esta leyenda solo me coloca los 2 primeros en la gráfica los demás no se ven.
    Segundo
    Quiero agrupar un grupo de valores y presentarlo en un vector columna, estos son los elementos
    c1=size(D(idx==1));
    c2=size(D(idx==2));
    c3=size(D(idx==3));
    c4=size(D(idx==4));
    c5=size(D(idx==5));
    c6=size(D(idx==6));
    c7=size(D(idx==7));

    me gustaria presentarlos todos o hacer una sentencia para que me imprima el grupo con mayor frecuencia.

    Espero que me puedas ayudar.
    Saludos

  9. Jahel Jahel

    Hola espero me puedas ayudar, tengo que ingresar una secuencia de 1 y 0, por ejemplo 0101010101011111111, y dividir la cadena cada 8 caracteres es decir si ingreso una secuencia de 24 con 0 y 1 debo obtener 3 vectores con 8 bits de 1 y 0. Muchas gracias

    • Hola Jahel. Creo que deberías poder hacerlo con algo así:

      original = ‘0101010101011111111’;
      for i = 1: 8: length(original)
      nuevos(j) = str(i : i +8)
      end

      Lo que hice fue primero tomar tu cadena original (usando la de tu ejemplo), luego hacer un loop en el que se crea un vector de palabras (nuevos) a base de tomar 8 cifras cada vez hasta llegar al final de la cadena original.

      Espero que te sirva. Saludos!

  10. Adriana Adriana

    Hola estoy tratando de hacer un código que me clasifique los datos en otro arreglo basandonos en la primera columna. Por ejemplo tengo el arreglo n=[120 0 0 0; 121 1 1 1; 120 1 1 1] y lo que quiero es tener dos arreglos. Uno en donde vayan los datos de 120 y otro donde vaya 121. n1=[120 0 0 0; 120 1 1 1] y n2=[121 1 1 1].

    Si me pudieras ayudar sería de gran ayuda.
    Muchas gracias.

    • Hola Adridana. Se me ocurre que podrías usar un find para buscar los que tengan el primer valor igual a 120 y a esos asignarles un índice, y lo mismo para el primer valor 121. Luego crearías nuevos arreglos en base a esos índices.

      n=[120 0 0 0; 121 1 1 1; 120 1 1 1]

      index_120=find(n==120)
      index_121=find(n==121)

      n_120=n(index_120,:)
      n_121=n(index_121,:)

      Si vas a hacerlo para separar muchos más valores, valdrá la pena que lo hagas con un bucle (con un for).

      Espero que te sirva la idea. Saludos!

  11. Giovanny Ramírez Giovanny Ramírez

    Buenas tardes.
    Tengo dos columnas de datos, una con valores de X y otra con valores de Y que son tomadas de sensores y en X tengo datos repetidos, estan repetidos porque estan redondeados a 2 decimales y en realidad tienen 3 o mas y pues quedan de 2 decimales, el caso es que a cada valor de ese repetido le corresponde un Y diferente, quisiera eliminar los repetidos pero conservando en Y el promedio de los valores para no simplemente despreciar su respectivo de X, un ejemplo tengo X=[0,02 0,03 0,02 0,04 0,02 0,03] y Y=[32,2 31,22 32,18 32,4 32,19 31,25], notese que los valores repetidos son 0,02 y 0,03 y quisiera obtener un solo 0,02 con su respectivo Y=(32,2+32,18+32,19)/3, y así con el 0,03 y todos los que se pudieran repetir dentro de los mas de 600 datos que tengo, la idea es organizarlos de esta manera y luego hacer una analisis de correlacion pero eso ya será otro tema, te agradezco una ayudita con mi duda.
    Feliz tarde

    • Hola Giovanny. Creo que yo lo haría así:

      Primero, identificaría los valores únicos que tienes en el vector X. Para ello haría: unicos_x=unique(X)
      En este caso la solución va a ser unicos_x=0.02 0.03 0.04

      Ahora buscaría los índices del vector X donde están cada uno de esos valores únicos, y haría los promedios de Y para cada uno de los valores repetidos en X.

      for i=1:length(unicos_x)
      indice=find(X==unicos_x(i))
      promedio(i)=mean(Y(indice))
      end

      Ahora, en ese vector «promedio» tienes los valores que buscabas. Espero que te sirva de ayuda.
      Saludos!

  12. Rogelio Flores Rogelio Flores

    hola
    Silvia Alonso Pérez

    hace poco inicié con la programación en matlab, y me he encontrado con un problema que me tiene confundido,

    1) Tengo un conjunto de datos del cual tengo que hacer una nube de puntos en la cual no se repitan datos y que tampoco aparezcan elementos cercanos, y esto lo tengo que realizar con el fin de determinar una curva que se aproxime a dicha nube de puntos, utilicé el comando «unique» y me elimina los datos repetidos pero me los acomoda de menor a mayor y «eso no es lo que pretendo» si no más bien que me elimine esos datos repetidos pero sin acomodarlos.

    2) Además que los datos cercanos también los elimine (lo cual no tengo idea con qué comando hacerlo o cómo hacerlo)

    3) De inicio lo que tengo es una muestra de datos de la cual le debo determinar su norma y compararla con un valor de Epsilon y partiendo de eso se empezaría a conformar la nube de puntos con un dominio y codominio (x,y).

    Espero me pueda dar algunas ideas.

    Gracias por su atención.

    Saludos
    Rogelio

    • Hola Rogelio. Nunca me he encontrado con ese problema, pero buscando información encontré hay argumentos opcionales en el comando unique que te permitirán que la salida no salga ordenada. Creo que es la opción «stable’

      Cuando dices «datos cercanos», ¿cuán cercanos? ¿Podrías poner un ejemplo?

      Saludos.

  13. A/Ndrés A/Ndrés

    Cordial saludo Silvia Alonso Pérez.
    Tú Blog está repleto de un sin fin de valiosa información que te agradezco muchísimo que compartas con nosotros.
    Hace poco que comencé a programar con Matlab y no encuentro la manera de resolver el siguiente código:
    Dadas dos matrices de m x n debo implementar los siguientes requisitos solicitados por el usuario:
    Solicitar los datos para llenar las celdas de la matriz. Los datos deberán ser valores reales ( Lo cual ya he logrado ejecutar).
    Y a partir de las dos matrices ingresadas por el usuario debo Identificar cuantos valores coinciden en la misma posición de las dos matrices.
    Adicionalmente debo Identificar cuales valores coinciden en la misma posición de las dos matrices como por ejemplo entre una matriz A y B se identificaron 5 coincidencias de valores en las mismas posiciones.
    Las coincidencias se identificaron en las siguientes posiciones.
    (1, 2)
    (2, 1)
    (2, 3)
    (3, 2)
    (3, 4)
    Espero que me puedas ayudar, realmente quiero aprender a resolver éste problema. Saludos desde Colombia. 🙂

  14. BRYAN JAVIER RIERA TAPIA BRYAN JAVIER RIERA TAPIA

    Hola, Silvia
    Excelente blog. Disculpa, si en mi vector hay dos números que se repiten [5 6 6 5 4] , cómo hago para que me aparezca que el dos se repite dos veces y el cinco dos veces. Un saludo. Muchas Gracias

  15. Ana Ana

    Hola, me sirvió mucho la información. En caso de que necesite conocer cual es el valor que más se repite (los datos de mi vector son texto) que código puedo usar?

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Verificado por MonsterInsights