IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

MATLAB Discussion :

Recherche dans des vecteurs et inclusions [Débutant]


Sujet :

MATLAB

  1. #1
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2013
    Messages : 401
    Points : 102
    Points
    102
    Par défaut Recherche dans des vecteurs et inclusions
    Bonjour à tous,

    J'ai un problème assez complexe à résoudre cette-fois ci.

    Disons qu'on se donne les deux vecteurs suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    X=[3 3 Y=[1 3
    11 11 10 12
    17 17 17 24
    24 24 29 35
    33 35 41 46 
    51 51 51 58
    57 58 60 65];
    64 65];
    Je les prend intentionnellement de tailles différentes car dans mon étude ils n'ont jamais le même nombre de colonnes mais toujours le même nombre de lignes : 2 lignes. A présent, pour ceux qui suivent mes affaires depuis le début, je pense que vous comprendrez aisément la suite : je vais appeler événement toute ligne de X : [3 3], [33 35] sont des événements par exemple. Cependant je veux les voir comme des intervalles d'entiers : [3 3] ={3}, [33 35] ={33;34;35} par exemple. De même dans le vecteur Y.

    Ce que je dois faire maintenant : pour un événement de X, je dois trouver le ou les événements correspondant de Y dans lequel cet événement de X est inclus. Pour simplifier on peut supposer qu'un événement de X est forcément inclus dans un seul de Y : par exemple pour [3 3], l'événement de Y que je recherche est [1 3], pour [11 11] il s'agit de [10 12] car [11 11] = {11} et 11 est bien inclus dans {10,11,12} = [10 12]. Voilà, et au final je veux stocker dans un vecteur Z les événements de X et à côté l'événement correspondant de Y, ce qui donnerait ici :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Z=[3 3 1 3
    11 11 10 12
    17 17 17 24
    24 24 17 24
    ect..
    Bref, j'ai commencé à m'embarquer dans quelque chose avec des boucles :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    for i=1:size(X,1)
        A1=[X(i,1):X(i,end)];
        for j=1:size(X,1)
            B1=[Y(j,1):Y(j,end)];
     
    %ect...

    Mais bon cela va vite devenir laborieux et très lent car j'ai plusieurs Y à utiliser et je ne sais pas vraiment comment partir. J'ai pensé aussi à essayer de faire l'intersection d'un événement de X avec tous ceux de Y et l'événément de Y qui est le bon serait celui où l'intersection est non vide mais ceci ne marche pas : intersect([3 3],Y) (malheuresement).

    EDIT:

    Ce qui se serait bien en fait c'est d'avoir une fonction I=indice(X,Y) qui retourne un vecteur I qui fournit les indices des positions dans Y que je recherche, soit ici :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    I=
     
    1
    2
    3
    3
    4
    6
    6
    ect...
    Mais bon j'ignore si c'est réalisable.

  2. #2
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2013
    Messages : 401
    Points : 102
    Points
    102
    Par défaut
    Bon j'essaye toute sorte de chose sans succès. Disons d'abord qu'on se donne un vecteur 2 lignes et 4 colonnes X par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    X=[3 3
    11 11
    17 17
    24 24
    33 35];
    Ainsi que le vecteur Y, 2 lignes 3 colonnes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Y=[1 3
    10 12
    17 24];
    J'ai besoin de travailler avec des intervalles de pas 1 donc des intervalles d'entiers comme je le mentionnais précédemment. Cependant, je voudrais utiliser la notation suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    X=[3:3
    11:11
    17:17
    24:24
    33:35];
    Mais cela ne marche pas puisqu'on aurait une sorte de matrice de taille "variable". J'ai pensé à essayer de stocker dans un tableau de cellule les cellules {3:3}, {11:11}...mais je n'arrive pas l'écrire distinctement, mais surtout que pourrais-je en faire dans mon contexte ?

  3. #3
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Une solution :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    X = [ ...
        3     3
        11    11
        17    17
        24    24
        33    35
        51    51
        57    58
        64 65];
    Y = [...
        1     3
        10    12
        17    24
        29    35
        41    46
        51    58
        60    65];
     
    isIn = bsxfun(@ge, X(:,1), Y(:,1).') & bsxfun(@le, X(:,1), Y(:,2).') | ...
           bsxfun(@ge, X(:,2), Y(:,1).') & bsxfun(@le, X(:,2), Y(:,2).');
     
    [xi yj] = find(isIn);
    Z = [X(xi,:) Y(yj,:)]

  4. #4
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2013
    Messages : 401
    Points : 102
    Points
    102
    Par défaut
    Merci pour cet effort Winjerome !

    Cela aurait été trop beau pour que cela marche d'un seul coup, en tout cas sur ma version MATLAB (7.0.1.24704 (R14) Service Pack 1) ! Les trois petits points sont-ils nécessaires ? En tout cas si je fais copier/coller les lignes que tu m'as proposées telles quelles, j'obtiens ces erreurs :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ??? Undefined command/function 'bsxfun'.
     
    ??? Undefined function or variable 'isIn'.
     
    ??? Undefined function or variable 'xi'.
    Il ne connait donc pas bsxfun mais je pense aussi que les solutions de ce type avec le "@" ne fonctionneront pas chez moi.

  5. #5
    Invité
    Invité(e)
    Par défaut
    Dans ce cas utilise la fonction repmat.
    Voir le Défi 2 : Pourquoi les matrices et les vecteurs ne s'entendent pas mieux ?

  6. #6
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2013
    Messages : 401
    Points : 102
    Points
    102
    Par défaut
    Merci Winjerome,

    Je n'arrive pas bien à comprendre cette page et la fonction que tu me proposes. Comment pourrais-t-on adapter ton code et sans les "..." ?

    En fait, je me suis lancé dans une méthode très bourrin car je voudrais déjà parvenir à un résultat :

    Premièrement, si on reprend les X et Y précédents :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    X = [3     3
    11    11
    17    17
    24    24
    33    35
    51    51
    57    58
    64 65];
    Y = [1     3
    10    12
    17    24
    29    35
    41    46
    51    58
    60    65];
    J'utilise deux boucles for pour stocker dans deux tableaux de cellules les événements comme je les entend i.e. chaque ligne de X et Y est vue comm un intervalle d'entiers :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    for i=1:size(X,1)
        JJ=[JJ;cell({X(i,1):X(i,end)})];
    end
     
    for i=1:size(Y,1)
        KK=[KK;cell({Y(i,1):Y(i,end)})];
    end
    Comme cela dans une case de JJ ou KK j'ai les intervalles comme je les veux. Ensuite je dois faire l'intersection des lignes de JJ avec celle de KK en utilisant la notation {} afin de "sortir" les intervalles que j'ai stocké dans les cellules. En gros je veux utiliser la fonction suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function vect=intersection_ligne_vecteur(ligne,vecteur)
     
    %Cette fonction fais l'intersection entre une ligne de la forme [deb:fin]
    %issue d'une cellule et toutes les lignes du même type d'un vecteur donné.
     
    vect=[];
     
    for i=1:size(vecteur,1)
        vect=[vect;intersect(ligne,vecteur{i,:})];
    end
    on peut l'appliquer par exemple comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    vect=intersection_ligne_vecteur(JJ{5,:},KK);
    J'obtiens alors dans vect l'intersection de la ligne 5 de JJ i.e. avec mon exmeple ce sera [33 34 35] avec toutes les lignes de KK ; en l'occurence l'intersection sera vide sauf, en reprenant mon vecteur Y avec l'événement [29 30 31 32 33 34 35] et le résultat est : [33 34 35]

    Malheuresement j'ai le warning suivant que je ne comprends pas :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Warning: Concatenation involves an empty array with incorrect number of columns.
    > In intersection_ligne_vecteur at 9
      In indice at 41
      In etude_de_courbe_reflux_extrema at 130
    La fonction semble marcher mais ce warning ralentit tout et je voudrais l'éviter.

  7. #7
    Invité
    Invité(e)
    Par défaut
    Perso je trouve ça plus lisible d'avoir tous les chiffres alignés plutôt que la première décalée comme toi. Maintenant tu fais ce que tu veux... et tu es assez grand pour les enlever toi-même.

    J'espère que tu as compris ma méthode, tu aurais au moins pu me montrer que tu voulais l'adapter sur ta version

    Dans le cas contraire :
    pour A = X(:,i) et B = Y(:,j).', A est un vecteur colonne de N éléments et B un vecteur ligne de M éléments, la ligne (ge étant la fonction correspondant à l'opérateur <= [greater equal]) va comparer chaque A(i) avec chaque B(j) pour au final obtenir un tableau 2D logique NxM.

    Toi qui ne possède pas cette fonction, tu dois faire en sorte d'avoir à comparer deux tableaux 2D de même taille NxM (ou faire une simple une boucle que tu aimes tant ) car comme tu as pu le voir j'espère dans la discussion, tu ne peux comparer directement deux tableaux de taille différente.
    On réplique donc M fois le vecteur colonne A et N fois le vecteur ligne B, et applique l'opérateur <= :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    repmat(A, 1, M) <= repmat(B, N, 1)
    à faire tu l'auras compris pour chaque bsxfun

    PS : n'hésite pas à exécuter au pas à pas avec des exemples simples et en décomposant les lignes pour bien comprendre, c'est le meilleur moyen pour cela

  8. #8
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2013
    Messages : 401
    Points : 102
    Points
    102
    Par défaut
    Winjerome, je te remercie pour toutes informations. Pour les "..." je comprends à présent qu'il s'agit simplement d'un alignement. En ce qui concerne ma méthode je crois que je vais laisser tomber car elle est trop complexe (stocker dans des tableaux de cellulles) mais surtout trop lente.

    En fait je veux absolument éviter les boucles mais pour le moment je n'arrive pas à faire sans. En cherchant un peu j'ai trouvé quelque chose qui semble marcher :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function Z=original_event(X,Y)
     
    for i = 1 : size(X,1)
       for j = 1 : size(Y,1)
           if X(i,1)>= Y(j,1) && X(i,2) <= Y(j,2)
               Z(i,1:2)=X(i,:);
               Z(i,3:4)=Y(j,:);
           end
     
       end
    end
    Mais ceci est bien lent dès lors que X et Y sont très grand (des centaines de milliers de données). Pourrais-t-on l'améliorer ?

    En ce qui concerne ta méthode, cela va te décevoir mais je reste assez perdu...tu voudrais donc remplacer le bsxfun et/ou ge par quelque chose avec repmat si je comprends bien. Et il s'agit d'adapter ce code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    isIn = bsxfun(@ge, X(:,1), Y(:,1).') & bsxfun(@le, X(:,1), Y(:,2).') | ...
           bsxfun(@ge, X(:,2), Y(:,1).') & bsxfun(@le, X(:,2), Y(:,2).');
     
    [xi yj] = find(isIn);
    Z = [X(xi,:) Y(yj,:)]
    En tout cas bsxfun ne marchera pas avec ma version.

    EDIT:

    Un petit complément : je suis en train de m'embarquer dans une fonction comme celle qui suit : X est fixe et il y a trois vecteurs auquel le comparer Y1,Y2,Y3 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    function Z=original_event(X,Y1,Y2,Y3)
     
    for i = 1 : size(X,1)
       for j = 1 : size(Y1,1)
           if X(i,1)>= Y1(j,1) && X(i,2) <= Y1(j,2) 
               Z(i,1:2)=X(i,:);
               Z(i,3:4)=Y1(j,:);
           end
     
       end
     
       for j = 1 : size(Y2,1)
           if X(i,1)>= Y2(j,1) && X(i,2) <= Y2(j,2)
               Z(i,5:6)=Y2(j,:);
           end
     
       end
     
      for j = 1 : size(Y3,1)
           if X(i,1)>= Y3(j,1) && X(i,2) <= Y3(j,2)
               Z(i,7:8)=Y3(j,:);
           end
     
       end
    Le problème c'est que j'aurai au maximum 6 Y différent et avec un tel code, la lenteur augmente au fur et à mesure.

    EDIT2:

    Bref j'ai poursuivi cette dernière méthode avec 4 5 et 6 Y. Cela fonctionne mais c'est vraiment lent car à chaque fois je rajoute une boucle for de plus. De plus j'ai pu m'entretenir avec un collègue qui a pu utiliser la méthode de Winjerome avec bsxfun mais il semble que l'utilisation des boucles for comme je les fais plus haut soit plus rapide dans son cas.

  9. #9
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2013
    Messages : 401
    Points : 102
    Points
    102
    Par défaut
    Finalement j'ai trouvé quelque chose comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    function Z=original_event_3(evenements_Imp123_liquide_melange,evenements_Imp1_liquide_melange,evenements_Imp2_liquide_melange,evenements_Imp3_liquide_melange)
     
    Z=zeros(size(evenements_Imp123_liquide_melange,1),8);
     
    Z(:,1)=evenements_Imp123_liquide_melange(:,1);
    Z(:,2)=evenements_Imp123_liquide_melange(:,2);
     
    for i=1:size(evenements_Imp123_liquide_melange,1)
     
        X1=find(evenements_Imp1_liquide_melange(:,1)<=evenements_Imp123_liquide_melange(i,1)); 
        X1b=find(evenements_Imp1_liquide_melange(:,2) >= evenements_Imp123_liquide_melange(i,2));
        X2=find(evenements_Imp2_liquide_melange(:,1)<=evenements_Imp123_liquide_melange(i,1)); 
        X2b=find(evenements_Imp2_liquide_melange(:,2) >= evenements_Imp123_liquide_melange(i,2));
        X3=find(evenements_Imp3_liquide_melange(:,1)<=evenements_Imp123_liquide_melange(i,1)); 
        X3b=find(evenements_Imp3_liquide_melange(:,2) >= evenements_Imp123_liquide_melange(i,2));
        Z(i,3)=evenements_Imp1_liquide_melange(X1(end),1);
        Z(i,4)=evenements_Imp1_liquide_melange(X1b(1),2);
        Z(i,5)=evenements_Imp2_liquide_melange(X2(end),1);
        Z(i,6)=evenements_Imp2_liquide_melange(X2b(1),2);
        Z(i,7)=evenements_Imp3_liquide_melange(X3(end),1);
        Z(i,8)=evenements_Imp3_liquide_melange(X3b(1),2);
     
    end
    Il n'y a plus qu'une boucle.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Comment indexer et rechercher dans des répertoires ?
    Par elitost dans le forum Windows XP
    Réponses: 2
    Dernier message: 18/07/2006, 21h01
  2. Réponses: 6
    Dernier message: 26/12/2005, 00h48
  3. recherche dans un vecteur
    Par ZaaN dans le forum C++
    Réponses: 2
    Dernier message: 20/12/2005, 12h53
  4. [XP] recherche dans des fichiers d'extension jsp
    Par drinkmilk dans le forum Windows XP
    Réponses: 5
    Dernier message: 20/10/2005, 08h55
  5. [FPDF] Rechercher dans des pdf
    Par snike dans le forum Bibliothèques et frameworks
    Réponses: 1
    Dernier message: 09/09/2005, 09h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo