J'ai un fichier avec le tableau de données suivant

7
1  2  3  120.12
4  5  8   70.25
6 11 12  111.20
2  6 10   90.39
3  2  1  120.12
10 6  2   90.39
11 2  3   87.12 
9
1  2  3  110.12
4  5  8   70.25
6 11 12  111.20
2  6 10   60.39
3  2  1  110.12
10 6  2   60.39
11 2  3   87.12
20 1  9  156.48
3  2 11   87.12 
...

Le fichier est composé de dizaines de datablocks. Chaque datablock a une ligne d'en-tête supérieure (nombre de lignes de données = taille du datablock), et la section de données a 4 colonnes. Ces 4 colonnes sont des angles pour 3 points. Les trois premières colonnes sont le numéro de point ou l'index de point. Et la 4ème colonne est l'angle de 3 points. Donc, c'est "angle ID1 ID2 ID3". Par exemple, "1 2 3 120.12" signifie un angle de 1-2-3 (le sommet est '2' dans ce cas) est de 120,12 degrés.

Le problème est qu'il y a des éléments qui se répètent. Dans la première image, il y a 2 paires répétitives: 1 2 3 et 3 2 1, et 2 6 10 et 10 6 2. Dans la deuxième image, il y a 3 éléments répétitifs, 1 2 3 et 3 2 1, et 2 6 10 et 10 6 2 et 11 2 3 et 3 2 11. Toutes ces paires ont le même angle, mais juste une direction opposée.

Comment puis-je exclure ces éléments répétitifs et n'en laisser qu'un pour chaque datablocks? Je souhaite que l'exemple ci-dessus devienne comme ceci:

5
1  2  3  120.12
4  5  8   70.25
6 11 12  111.20
2  6 10   90.39
11 2  3   87.12 
6
1  2  3  110.12
4  5  8   70.25
6 11 12  111.20
2  6 10   60.39
11 2  3   87.12
20 1  9  156.48
...

Je souhaite obtenir la distribution et le PDF normal de l'angle pour chaque datablocks et pour tous les angles indépendamment des angles. Mais je ne sais pas comment puis-je exclure ces combinaisons répétitives.

Il y a peu de chances que le même angle se produise `` heureusement '' avec un combo différent, donc j'essayais d'exclure les éléments répétitifs en fonction des numéros d'identification, comme ID1 ID2 ID3 répété par ID3 ID2 ID1. Mais je n'ai pas trouvé de logique appropriée pour la boucle if et la boucle for ou la fonction ...

1
exsonic01 21 avril 2020 à 07:36

2 réponses

Meilleure réponse

Disons que vous avez séparé vos blocs et que l'un des blocs est stocké sous la forme d'un double tableau n-par-4 block.

Ce dont vous avez besoin, c'est de trier les sommets de chaque ligne tout en gardant le 2ème fixe. Cela peut être réalisé en utilisant sort le long de la dimension de ligne comme suit

sort([block(:,1),block(:,3)],2);

La deuxième entrée 2 spécifie le tri de toutes les lignes le long de la colonne.

Ensuite, vous devez rajouter les 2e sommets et choisir les combinaisons de sommets uniques.

unique([block(:,2),sort([block(:,1),block(:,3)],2)],'row');

'row' signifie sélectionner des lignes uniques dans leur ensemble, au lieu d'éléments individuels uniques. Vous pouvez ajouter 'stable' pour conserver la commande existante. Mais vous n'avez pas précisé un tel besoin dans la question. Je vais donc le garder facultatif.

Pour obtenir l'ordre des sommets d'origine, nous utilisons les indices des lignes uniques comme suit. Ici, vous devez vous assurer que les angles en double identifiés par une séquence de sommets valide ont la même valeur d'angle. (Sinon, vous devez ajouter block(:,4) à la formule ci-dessus.)

[~, ind] = unique([block(:,2),sort([block(:,1),block(:,3)],2)],'row');

Et votre réponse finale est: (juste les deux lignes ci-dessous)

[~, ind] = unique([block(:,2),sort([block(:,1),block(:,3)],2)],'row');
block(ind,:),
ans =
    1.0000    2.0000    3.0000  120.1200
   11.0000    2.0000    3.0000   87.1200
    4.0000    5.0000    8.0000   70.2500
    2.0000    6.0000   10.0000   90.3900
    6.0000   11.0000   12.0000  111.2000

Si quelqu'un pouvait écrire une réponse basée sur une boucle avec mise en cache manuelle, je serais curieux de voir entre ce qui précède et la boucle avec la mise en cache manuelle, laquelle est la plus rapide.

1
Argyll 21 avril 2020 à 05:49

Il s'agit d'un travail classique pour accumarray . Comme vous n'avez fourni aucun code pour charger les données, je viens de le lire avec readmatrix. Vous devrez peut-être adapter le code si vous le chargez d'une autre manière.

% given
DATA = readmatrix('data.txt','NumHeaderLines',0);      % load data
DATA(:,end) = [];                                      % remove last column, as only NaN

hl = any(isnan(DATA(:,2:end)),2);                      % identify header lines
subs = cumsum(hl);                                     % indices for accumarray

% unqiue rows of chunks of data
y = accumarray(subs(:), ...                            % indices of chunks
               1:numel(subs).', ...                    % numbering of rows
               [], ...                                 % not used
               @(x) { ...                              % anonymous function
               unique( ...                             % unique 'rows' of chunks
               [sort( DATA(x,1:3), 2) DATA(x,4)], ...  % first 3 columns sorted
               'rows', 'stable' ...                    % stable -> do not change order
               )});
y = cell2mat(y);                                       % tranfsform back to array

y =

    7.0000       NaN       NaN       NaN
    1.0000    2.0000    3.0000  120.1200
    4.0000    5.0000    8.0000   70.2500
    6.0000   11.0000   12.0000  111.2000
    2.0000    6.0000   10.0000   90.3900
    2.0000    3.0000   11.0000   87.1200
    9.0000       NaN       NaN       NaN
    1.0000    2.0000    3.0000  110.1200
    4.0000    5.0000    8.0000   70.2500
    6.0000   11.0000   12.0000  111.2000
    2.0000    6.0000   10.0000   60.3900
    2.0000    3.0000   11.0000   87.1200
    1.0000    9.0000   20.0000  156.4800
1
thewaywewalk 21 avril 2020 à 05:11