2017-08-03 1 views
0

Compte tenu de ces deux ensembles de données:Étant donné deux ensembles de données avec 3 colonnes, extraire les lignes pour lesquelles la valeur de la troisième colonne est à peu près égale dans les deux ensembles de données

data_set_1.txt: https://pastebin.com/VQrsv8kU

data_set_2.txt: https://pastebin.com/jFBa6kZq

(Il est possible de les télécharger sans vous inscrire)

Je suis en train d'obtenir les valeurs de x_1, y_1, x_2 et y_2 pour lesquels:

z_1 = z_2 (dans un seuil).

Existe-t-il un moyen de le faire?

1) Les deux ensembles de données ne sont pas la même longueur,

2) Depuis z_1 et z_2 ne sera jamais exactement égal, j'ai essayé ce qui suit:

import numpy as np 
y_1, z_1, x_1 = np.loadtxt('./data_set_1.txt').T  
y_2, z_2, x_2 = np.loadtxt('./data_set_2.txt').T 

threshold = 0.000005 
for i in z_1: 
for j in z_2: 
    if abs(i - j) < threshold: 
    print "i = ", ('%.13f' % i) 
    print "j = ", ('%.13f' % j) 

Le résultat est le suivant :

i = -941.4594925722633 
j = -941.4594947788443 
i = -941.4456535625201 
j = -941.4456565008313 
i = -941.4291125503427 
j = -941.4291149979141 
i = -941.4326065311985 
j = -941.4326072530644 
i = -941.4098552554067 
j = -941.4098593315858 
i = -941.4138389914422 
j = -941.4138343941854 
i = -941.3961673813864 
j = -941.3961719676133 
i = -941.3984112845883 
j = -941.3984098947884 
i = -941.3838698217477 
j = -941.3838733787329 
i = -941.4001013025463 
j = -941.4001055479807 

Il est possible de vérifier que cela fonctionne parce que i = -941.4594925722633 se trouve sur laLa colonnede ./data_set_1.dat et j = -941.4594947788443 est trouvée sur ./data_set_2.dat.

Maintenant, chacun de ces imprimés i résultats contiennent une x_1 et y_1

De même, chacun de ces j résultats contiennent une x_2 et y_2

Je ne parviens pas à extraire x_1, y_1, x_2 et y_2

+0

Vous ne nous montrez aucune de vos propres tentatives. Avez-vous essayé quelque chose vous-même, et quels ont été les problèmes avec cette approche? En outre, voulez-vous une approche qui évolue bien pour les ensembles de données plus volumineux? –

+0

@RoryDaulton Oui, désolé, j'ai eu quelques tentatives, (je voulais juste garder la question courte) - édité –

+0

@Rory Daulton Fait –

Répondre

0

Voici un aperçu d'une approche qui fonctionnerait.

Trier chaque jeu de données dans l'ordre croissant par les valeurs de z: c'est-à-dire z_1 et z_2. Ensuite, définissez un index pour chaque ensemble de données. Parcourez-les en avançant un index lorsque l'élément de cet ensemble de données est trop faible pour être comparé à l'élément pointé dans l'autre ensemble de données. Lorsque les éléments comparés sont suffisamment proches, agissez sur la paire d'éléments. Vous avez terminé lorsque les deux indices atteignent la fin de leurs jeux de données. Ceci est similaire à comment se fait Mergesort. Les différentes tailles des jeux de données n'affecteront pas l'algorithme.

Cet algorithme ne ressemble pas particulièrement à Pythonic et n'utilise pas les forces de numpy mais il a l'avantage que cela fonctionne. Cette deuxième étape a une complexité de temps O(n) donc c'est rapide. L'étape de tri a la complexité du temps O(n log(n)) donc c'est la partie lente.


En ce qui concerne votre code supplémentaire tentative: i et j sont pauvres noms de variables pour les valeurs de z_1 et z_2. Si ndx1 et ndx2 sont les indices dans vos deux ensembles de données et le « seuil » pour l'égalité est threshold, vous pouvez tester pour quasi-égalité avec:

if abs(z_1[ndx1] - z_2[ndx2]) < threshold: 
    do_whatever 

La valeur de threshold serait quelque chose comme 1e-5.

Mais ici, le code est plus étroitement lié à ce que vous voulez. Cela suppose que les ensembles de données sont déjà configurés et triés par leurs valeurs z.

threshold = 1e-5 

length1, length2 = len(z_1), len(z_2) 
if length1 == 0 or length2 == 0: 
    return 
ndx1 = ndx2 = 0 
z1, z2 = z_1[0], z_2[0] 

while True: 
    if z1 + threshold <= z2: # z_1 too low 
     ndx1 += 1 
     if ndx1 == length1: 
      return 
     z1 = z_1[ndx1] 
    elif z2 + threshold <= z1: # z_2 too low 
     ndx2 += 1 
     if ndx2 == length2: 
      return 
     z2 = z_2[ndx2] 
    else: # z_1 and z_2 almost equal 
     do_whatever 
     # adjust ndx1, ndx2 

Ceci est juste un squelette. Comment ajuster ndx1 et ndx2 à la fin dépend de si vous voulez permettre une valeur de z_1 étant presque égale à plus de la valeur de z_2 ou l'inverse.

+0

Si vous exécutez 'si abs (z_1 [ndx1] - z_2 [ndx2 ])

0

est ici un début difficile en utilisant seulement numpy:

idx = abs(z1 - z2[:, None]) < threshold 
idx1 = idx.any(0) 
idx2 = idx.any(1) 

idx1 et idx2 peut ensuite être utilisé pour obtenir les lignes associées, par exemple avec y1[idx1], y2[idx2], etc.

Le code fonctionne en faisant un comparaison par paires de tous les éléments de z1, z2, puis de trouver tout élément où l'une de ces comparaisons est inférieure au seuil.
Pour un grand ensemble de données, la réponse de Rory sera plus rapide et utilisera beaucoup moins de mémoire puisqu'il ne calcule la comparaison que lorsque cela est nécessaire. Pour les ensembles de données plus petits, comme celui donné, l'accélération de l'élimination des boucles devrait être importante.

+0

Merci pour votre réponse, mais avec ce code, vous vous retrouvez avec des booléens au lieu des valeurs réelles - veuillez voir la mise à jour –

+0

@DavidC Numpy permet d'utiliser des tableaux booléens pour indexer un tableau de taille similaire. J'ai modifié pour inclure un exemple de ceci. – user2699