2017-10-13 5 views
1

EDIT ::::: Je dois donc utiliser ceci pour les coordonnées x et y. Donc DF1 a 5384167 paires et le DF2 a 1928 paires. Je comprends comment fonctionne la solution de @Divakar pour une variable. Dans mon cas précis, j'ai des coordonnées de métro et je voudrais comparer leur proximité avec les coordonnées du crime. Voir s'il y a une corrélation avec le type de crime et la distance euclidienne de la station de métro la plus proche.Différence absolue entre les variables dans les colonnes de différentes longueurs

Je sais que sqrt (DF1 [x] -DF2 [x]) ** 2 + (DF1 [y] -DF2 [y]) ** 2) doit être fait entre tous les X, Y dans les emplacements de métro et chaque X, Y dans les lieux de crime.

Crime Coordonnées:

X_COORD_CD Y_COORD_CD 0 1007314.0 241257.0 1 1043991.0 193406.0 2 999463.0 231690.0 3 1060183.0 177862.0 4 987606.0 208148.0

métro Coordonnées:

X_COORD_CD Y_COORD_CD 0 1020671.0 248680.0 1 1019420.0 245867.0 2 1017558.0 245632.0

X_Crime Y_Crime X_Subway Y_Subway Dist_sub1 Dist_sub2 Dist_sub3 1007314 241257 1020671 248680 13356.72213 12105.8096 10243.78646 1043991 193406 1019420 245867 23318.81485 24569.93244 26432.01209 999463 231690 1017558 245632 21207.59944 19956.64481 18094.61475 1060183 177862 39511.10383 40762.16584 42624.20504 987606 208148 33064.38708 31813.40719 29951.37426

si Dist_sub1 [0] = ((X_Crime [0] - X_Subway [0]) ** 2 + (Y_Crime [0] - Y_Subway [0]) ** 2) ** 0,5

Dist_sub2 [3] = ((X_Crime [3] - X_Subway [1]) ** 2 + (Y_Crime [3] - Y_Subway [1]) ** 2) ** 0,5

Ainsi, la distance minimale à un métro pour Crime [0] est 10243.78646 (Subway [2]); Le crime [1] est 23318.81485 (Métro [0]); Le crime [2] est 18094.61475 (Subway [2]); Le crime [3] est 39511.10383 (Métro [0]); Crime [4] est 29951,37426 (métro [2])

FIN DE MODIFIER

j'ai une liste de coordonnées x et y dans deux dataframes séparées. L'un a 5384167 entrées et l'autre 1928 entrées. J'essaie de comprendre comment calculer la distance absolue entre chaque entrée dans df1 et df2, puis trouver le minimum. Exemple:

DF1:

x 
1 
2 
3 

DF2:

x 
4 
5 
6 
7 

Je sais que la création d'une matrice est le chemin à parcourir, mais je ne sais littéralement pas comment y arriver. La matrice ressemblerait à ceci:

3 2 1 
4 3 2 
5 4 3 
6 5 4 

Puis j'obtenir le minimum pour chaque colonne:

3 2 1 
+0

Pourriez-vous nous montrer un exemple de cas où le tri à la première étape est chambouler/ne pas donner les résultats attendus? – Divakar

+0

@Divakar désolé à ce sujet. Je vais modifier le message original et inclure un véritable échantillon de chaque liste. –

+0

En outre, ajoutez la sortie attendue si vous ne l'avez pas déjà fait. – Divakar

Répondre

1

Deux approches pourraient être proposées.

Approche # 1

Une approche avec NumPy broacasting avec les exigences de mémoire lourds serait -

def abs_min_broadcasting(a, b): # a, b are input arrays 
    return np.abs(a[:,None]-b).min(axis=0) 

output = abs_min_broadcasting(df2.x.values, df1.x.values) 

Approche # 2

Un autre efficace de la mémoire et en tant que telle plus vite on pourrait être avec np.searchsorted -

def abs_min_searchsorted(a, b): # a, b are input arrays 
    a_s = np.sort(a) # skip this if already sorted 
    lidx = np.searchsorted(a_s,b).clip(max=len(a_s)-1) 
    ridx = (lidx-1).clip(min=0) 
    return np.minimum(np.abs(a_s[lidx] - b), np.abs(a_s[ridx] - b)) 

output = abs_min_searchsorted(df2.x.values, df1.x.values) 

run échantillon -

In [866]: df1 
Out[866]: 
    x 
0 1 
1 2 
2 3 

In [867]: df2 
Out[867]: 
    x 
0 4 
1 5 
2 6 
3 7 

In [869]: abs_min_broadcasting(df2.x.values, df1.x.values) 
Out[869]: array([3, 2, 1]) 

In [870]: abs_min_searchsorted(df2.x.values, df1.x.values) 
Out[870]: array([3, 2, 1]) 

Test d'exécution -

In [872]: df1 = pd.DataFrame({'x':np.random.randint(0,100,(10000))}) 

In [873]: df2 = pd.DataFrame({'x':np.random.randint(0,100,(1000))}) 

In [874]: %timeit abs_min_broadcasting(df2.x.values, df1.x.values) 
10 loops, best of 3: 28.4 ms per loop 

In [875]: %timeit abs_min_searchsorted(df2.x.values, df1.x.values) 
1000 loops, best of 3: 663 µs per loop 

In [876]: out1 = abs_min_searchsorted(df2.x.values, df1.x.values) 
    ...: out2 = abs_min_broadcasting(df2.x.values, df1.x.values) 
    ...: print np.allclose(out1, out2) 
    ...: 
True