[PYTHON] C'est pourquoi je pourrai rechercher de petites circonscriptions à partir de mon emplacement actuel

Un an après la levée de l'interdiction des élections en ligne, la transmission en ligne des responsables officiels des partis politiques s'est transformée en un jeu extrême qui ne cesse de réduire la valeur SAN des partisans comme une bonite, comment allez-vous tous aujourd'hui? Maintenant, réfléchissons à la façon d'obtenir des informations sur la petite circonscription à partir de votre emplacement actuel.

résultat

http://needtec.sakura.ne.jp/analyze_election/page/ElectionArea/shuin_47

Sur cette page, vous pouvez voir les candidats pour les petites circonscriptions en sélectionnant une préfecture ou en obtenant votre emplacement actuel. De plus, en sélectionnant une petite circonscription, l'emplacement approximatif de la circonscription et une liste de candidats seront affichés.

Code source

https://github.com/mima3/analyze_election

Bibliothèques dépendantes lxml-3.4.0-py2.7-freebsd-9.1-RELEASE-p15-amd64.egg rdp-0.5-py2.7.egg numpy-1.9.1-py2.7-freebsd-9.1-RELEASE-p15-amd64.egg sympy-0.7.5-py2.7.egg Beaker-1.6.4-py2.7.egg

sympy ne fonctionne qu'avec 0.7.5

Des données d'utilisation

** Informations numériques sur les terres nationales Données sur la zone administrative ** http://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-N03.html

** District électoral des membres de la petite circonscription électorale de la Chambre des représentants (par préfecture) ** http://www.soumu.go.jp/senkyo/senkyo_s/news/senkyo/shu_kuwari/

Données obtenues en convertissant manuellement ce qui précède en CSV https://github.com/mima3/analyze_election/blob/master/election_area.csv

** Asahi Shimbun Digital> Élection à la Chambre des représentants 2014> Candidat ** http://www.asahi.com/senkyo/sousenkyo47/kouho/

Données converties de ce qui précède en CSV https://github.com/mima3/analyze_election/blob/master/script/candidate_shuin_47.csv

Procédure de création de données

#Créer une base de données
python create_db.py election.sqlite

#Information numérique foncière nationale Importation des données de la zone administrative Elle sera terminée dans quelques heures!
python import_administrative_boundary.py election.sqlite area\N03-14_140401.xml

#Conversion des données de la zone administrative en sympy Polygon Cela prend environ 24 heures!
python convert_poly.py election.sqlite

#Enregistrer les informations sur les petites circonscriptions
python import_election_area.py election.sqlite election_area.csv

#Enregistrer les informations sur les candidats pour les petites circonscriptions
python import_candidate.py election.sqlite shuin_47 script\candidate_shuin_47.csv
 

Commentaire

Données de la zone administrative

Les données de zone administrative sont fournies en XML pour les informations numériques sur les terres nationales. Si vous l'utilisez, vous pouvez afficher la division du district administratif sur Google Map. Cependant, comme ces données sont énormes, il y a quelques précautions à prendre lors de leur manipulation.

Analyser du XML de grande taille

Lors de l'analyse d'un XML de grande taille, si vous convertissez le fichier XML en caractères et que vous l'analysez, l'utilisation de la mémoire augmentera considérablement et vous ne pourrez pas le traiter.

Par conséquent, utilisez lxml.etree.iterparse pour traiter de manière séquentielle. Voyons le traitement réel.

election_db.py


    def ImportAdministrativeBoundary(self, xml):
        f = None
        contents = None
        namespaces = {
            'ksj': 'http://nlftp.mlit.go.jp/ksj/schemas/ksj-app',
            'gml': 'http://www.opengis.net/gml/3.2',
            'xlink': 'http://www.w3.org/1999/xlink',
            'xsi': 'http://www.w3.org/2001/XMLSchema-instance'
        }
        self._conn.execute('begin')

        print ('admins....')
        context = etree.iterparse(xml, events=('end',), tag='{http://nlftp.mlit.go.jp/ksj/schemas/ksj-app}AdministrativeBoundary')
        for event, admin in context:
            adminId = admin.get('{http://www.opengis.net/gml/3.2}id')
            print (adminId)
            bounds = admin.find('ksj:bounds', namespaces=namespaces).get('{http://www.w3.org/1999/xlink}href')[1:]
            prefectureName = admin.find('ksj:prefectureName', namespaces=namespaces).text
            subPrefectureName = admin.find('ksj:subPrefectureName', namespaces=namespaces).text
            countyName = admin.find('ksj:countyName', namespaces=namespaces).text
            cityName = admin.find('ksj:cityName', namespaces=namespaces).text
            areaCode = admin.find('ksj:administrativeAreaCode', namespaces=namespaces).text
            sql = '''INSERT INTO administrative_boundary
                     (gml_id, bounds, prefecture_name, sub_prefecture_name, county_name, city_name, area_code)
                     VALUES(?, ?, ?, ?, ?, ?, ?);'''
            self._conn.execute(sql, [adminId, bounds, prefectureName, subPrefectureName, countyName, cityName, areaCode ])

            admin.clear()
            # Also eliminate now-empty references from the root node to <Title> 
            while admin.getprevious() is not None:
                del admin.getparent()[0]
        del context

Le code ci-dessus fait partie du processus qui analyse les informations numériques sur les terres nationales et les stocke dans la BD. Dans cet exemple, etree.iterparse est utilisé pour traiter chaque fois que la balise «Administrative Boundary» est détectée.

Pour plus de détails, reportez-vous à la page suivante. ** Utilisez lxml pour l'analyse syntaxique XML haute performance en Python ** http://www.ibm.com/developerworks/jp/xml/library/x-hiperfparse/

Éclaircir les informations de coordonnées

La taille des données numériques nationales sur les terres est importante car elles stockent des informations de coordonnées précises. Cette fois, nous avons seulement besoin de connaître les coordonnées approximatives, nous allons donc éclaircir ces informations.

Il existe un algorithme appelé Ramer-Douglas-Peucker comme algorithme pour amincir les lignes. Voir la page ci-dessous pour une description de cet algorithme.

** [Mathematica] affine la ligne de pliage ** http://www.330k.info/essay/oresenwomabiku

Les éléments suivants sont disponibles en tant que modules de l'algorithme Ramer-Douglas-Peucker de Python. https://pypi.python.org/pypi/rdp

Enregistrement des informations pour les petites circonscriptions

Comme d'habitude, le ministère des Affaires intérieures et des Communications ne publie des informations sur les petites circonscriptions qu'au format PDF. Vous devez donc faire de votre mieux pour le saisir manuellement ou essayer une autre méthode.

De plus, les informations sur les petites circonscriptions sont étonnamment floues. Par exemple, prenez les premier et deuxième quartiers de la préfecture d'Iwate. http://www.soumu.go.jp/main_content/000240041.pdf

Daiichi Ward Ville de Morioka (juridiction du bureau principal, juridiction de la succursale de Morioka City Hall Aoyama, juridiction de la filiale de Morioka City Hall de Yanagawa, juridiction de la filiale de Morioka City Hall Ota, juridiction de la filiale de Morioka City Hall, juridiction de la branche générale de Morioka City Tonan)

Deuxième quartier de la ville de Morioka (zone qui n'appartient pas au premier quartier)

Il y a. Bien entendu, aucune information n'est fournie ici sur la position de la juridiction de l'Office. Par conséquent, cette fois, dans le cas de la ville de Morioka, les premier et deuxième quartiers sont répertoriés comme candidats pour la petite circonscription électorale.

Le CSV créé en crachant une malédiction sur le ministère de l'Intérieur et des Communications, qui a la ferme intention de ne pas analyser les données de cette manière, est le suivant. https://github.com/mima3/analyze_election/blob/master/election_area.csv

De plus, comme j'ai été tellement impressionné ici, je tire des informations sur les candidats de l'Asahi Shimbun. Dans le script ci-dessous, ce type de données est manquant, je l'utilise donc à la main si nécessaire.

https://github.com/mima3/analyze_election/blob/master/script/analyze_asahi.py

Obtenez une petite circonscription de votre emplacement actuel.

Obtenez votre position actuelle dans votre navigateur.

Pour utiliser votre position actuelle dans votre navigateur, utilisez navigator.geolocation. Vous pouvez obtenir la longitude et la latitude avec le code suivant.

if (!navigator.geolocation) {
  //Traitement pour les environnements où l'API de géolocalisation ne peut pas être utilisée
  alert('L'API Geolocate n'est pas disponible');
}
navigator.geolocation.getCurrentPosition(function(position) {
  console.log(position)
}

Dans le cas d'IE, la position actuelle est gravement déplacée. Cela est probablement dû au fait que la base de données d'utilisation de l'emplacement utilisée par Microsoft est moins précise que la base de données d'informations de localisation utilisée par Chrome et Firefox. (Je ne suis pas mal! Je ne suis pas mal!) https://social.technet.microsoft.com/Forums/ie/en-US/aea4db4e-0720-44fe-a9b8-09917e345080/geolocation-wrong-in-ie9-but-not-other-browsers

Découvrez si une coordonnée particulière est incluse dans la zone administrative.

Savoir si une coordonnée particulière est contenue dans une zone administrative a la même signification que vérifier si un point est contenu dans un polygone. Dans le cas de Python, c'est bon pour ** basique ** si vous utilisez SymPy pour juger l'intérieur et l'extérieur du point.

** [Python] Utilisez SymPy pour juger à l'intérieur et à l'extérieur des points ** http://d.hatena.ne.jp/factal/20121013

En gros, je l'ai dit parce que ce processus est si lent. Il faudrait trop de temps pour travailler sur des dizaines de milliers de districts administratifs un par un.

Pour cette raison, nous avons pris ici deux mesures.

Commencez par réduire le nombre de polygones cibles avant de faire un point de jugement intérieur / extérieur. Ceci n'est recherché que si la distance entre les sommets du polygone et le point spécifié est dans une certaine plage.

Plus précisément, le code est le suivant.

election_db.py


    def GetPos(self, lat, long):
        """
Obtenez des données de courbe associées à la longitude et à la latitude actuelles
        """
        m =0.005
        while 1:
            rows = self._getCurveId(lat, long, m).fetchall()
            if rows:
              break
            m = m * 2
            if m > 0.1:
              return None

        dict = {}
        pt = Point(lat, long)

        for r in rows:
            key = r[0]
            ret = self._isCrossCurveId(pt, key)
            if ret:
                return ret
        return None

La seconde consiste à créer un objet Polygon à l'avance et à l'enregistrer dans la base de données. Plus précisément, la mise en œuvre est la suivante.

    def ConvertPoly(self):
        """
Création d'un polygone à partir de la table de courbes
        """
        #gc.enable()
        #gc.set_debug(gc.DEBUG_LEAK)
        sql = '''DELETE FROM polygon'''
        self._conn.execute(sql)

        sql = '''select curve_id,lat,lng from curve order by curve_id'''
        rows = self._conn.execute(sql)
        dict = {}
        for r in rows:
            key = r[0]
            if dict.get(key) is None:
                dict[key] = []
            dict[key].append((r[1], r[2]))
        i = 0
        self.Commit()

        self._conn.execute('begin')
        for key in dict:
            print (key + ":" + str(i))
            #b = len(gc.get_objects())
            self._createPoly(key, dict[key])
            i = i + 1
            #gc.collect()
            #print str(b) + ":" + str(len(gc.get_objects()))
            if i % 100 == 0:
                clear_cache()
                self.Commit()

    def _createPoly(self, key, list):
        poly = Polygon(*list)
        obj = pickle.dumps(poly)
        sql = '''INSERT INTO polygon
                       (curve_id, object)
                     VALUES(?, ?);'''
        self._conn.execute(sql, [key, obj ])
        del poly
        del obj

Utilisez pickle.dumps pour sérialiser l'objet. De plus, comme sympy utilise un mécanisme de mise en cache, la création d'un grand nombre d'objets consomme rapidement plusieurs Go de mémoire. Pour éviter cela, afin de créer 100, clear_chache est utilisé pour supprimer le cache.

De plus, les conditions de sortie d'une exception "Polygon a des côtés qui se croisent." Dans la dernière sympy Polygon sont différentes entre 0.7.5 et 0.7.6. Les conditions sont plus strictes dans la version 0.7.6 et ces données ne peuvent pas être créées normalement. Par conséquent, utilisez 0.7.5 pour sympy.

Recommended Posts

C'est pourquoi je pourrai rechercher de petites circonscriptions à partir de mon emplacement actuel
Tout pour que les débutants puissent faire du machine learning