Boucle double ds Stata avc 2bases de données

cosimowinckler Messages postés 1 Statut Membre -  
 cosimowinckler -
Bonjour,

J'essaie depuis deux jours de programmer une double boucle dans Stata (version 9) sans succès et aurais désespérément besoin d'aide.

L'idée générale est la suivante. Je dispose de coordonnées géographiques de points de clusters d'une enquête dans une base de données et d'un nuage de coordonnées géographiques d'une frontière dans l'autre (numérotés du premier au dernier point). Je dispose aussi d'une formule permettant de calculer la distance en km entre deux coordonnées.

Ce que je veux faire est pour chaque coordonnée d'un cluster de l'enquête calculer le point de la frontière le plus proche et le garder la distance calculée si celle-ci est de moins de 100km.

Voici la formule que j'utilise pour obtenir la distance entre deux coordonnées géographiques en degrés est la suivante pour deux points de coordonnées (x1,y1) (x2,y2) (x=Latitude, y=Longitude). La division par pi permet de convertir les degrés en radians et j'ai pris 3963,1 comme rayon de la terre.

Arcos( cos(x1/pi)cos(y1/pi)cos(x2/pi)cos(y2/pi) + cos(x1/pi)sin(y1/pi)cos(x2/pi)sin(y2/pi) + sin(x1/pi)sin(x2/pi) ).3963,1

Ceci qui donne dans Stata:
acos(cos(x1/_pi)*cos(y1/_pi)*cos(x2/_pi)*cos(y2/_pi) + cos(x1/_pi)*sin(y1/_pi)*cos(x2/_pi)*sin(y2/_pi) + sin(x1/_pi)*sin(x2/_pi) )*3963,1

Pour calculer une distance entre les clusters de l'enquête et une ville en particulier voici un programme qui marche:

sort LAT1 LONG1
duplicates drop
gen ordre_coord=_n
if LAT1!=. & LONG1!=. {
foreach x of varlist ordre_coord {
gen x_`x'=acos(cos(LAT1/_pi)*cos(LONG1/_pi)*cos(LAT2/_pi)*cos(LONG2/_pi) + cos(LAT1/_pi)*sin(LONG1/_pi)*cos(LAT2/_pi)*sin(LONG2/_pi) + sin(LAT1/_pi)*sin(LAT2/_pi) )*3963,1
}
}
else gen dist_cap=.
rename x_ordre_coord dist_ville1_ville2

Pour le problème qui m'inquiète, j'ai essayé en combinant deux foreach et/ou des forvalues et/ou des macros locales. Le problème que je rencontre est que je n'arrive pas à faire que Stata calcule pour chaque couple de coordonnées cluster même une des distances avec les coordonnées frontière (et donc a fortiori le reste) puisqu'elles se trouvent 500 observations plus bas à cause du append.

Une piste que je n'ai pas explorée mais que je n'arrive pas plus à programmer pourrait être de créer une base plus grande où chaque coordonnée cluster est mise devant les coordonnées frontières (ie 550x70 lignes). Il suffirait ensuite de calculer les distances pour chaque ligne, garder la distance minimale pour une combinaison LAT/LONG cluster donnée et l'éliminer ou la garder selon si elle satisfait la condition des 100km.

Toute aide est la bienvenue... J'espère avoir été clair au moins..

Cosimo
A voir également:

1 réponse

cosimowinckler
 
Voici la solution que j'avais trouvée (68 points pour la frontière, 115 km étant la barre sup. audessus de laquelle les points ne m'intéressaient pas):

forvalues X=1/68{
gen dist`X' = acos(cos(LAT)*cos(LATfr_`X')*cos(LONGfr_`X' - LONG) + sin(LAT)*sin(LATfr_`X'))*6372.795
}
forvalues X=1/68{
replace dist`X' =. if dist`X' > 115
}

gen dist_frontSENMAU_100km=.
gen dist0=116
forvalues i=1/68 {
local i0=`i'-1
replace dist_frontSENMAU_100km=dist`i' if dist`i'<dist`i0'
replace dist`i'=dist`i0' if dist`i'>= dist`i0'
}
1
cosimowinckler
 
(Elément supplémentaire, j'avais ajouté à chaque ligne d'observation dans la base une ligne comprenant les coordonnées pour les 68 points frontière, le calcul en boucle se fait ensuite ligne à ligne.. ; il suffisait ensuite de rajouter une boucle pour supprimer toutes les nouvelles variables)
0