Ceci est le 4ème volet de la série Twitter Starva. Cette fois, je souhaite traiter les informations de localisation contenues dans les données du tweet!
Partie 1: Importez des données avec les API REST Twitter et importez-les dans mongoDB http://qiita.com/kenmatsu4/items/23768cbe32fe381d54a2
Partie 2: Séparation du spam des données Twitter acquises http://qiita.com/kenmatsu4/items/8d88e0992ca6e443f446
Partie 3: Pourquoi le nombre de tweets a-t-il augmenté après un jour? http://qiita.com/kenmatsu4/items/02034e5688cc186f224b
Partie 4: Visualisation des informations de localisation cachées dans Twitter (cette fois) http://qiita.com/kenmatsu4/items/114f3cff815aa5037535
** <<< Données à analyser >>> **
** Schéma de principe de ce contenu **
Cette fois aussi, nous analyserons les tweets qui incluent "staba" dans le texte. En outre, en plus des informations de latitude et de longitude attachées au tweet lui-même, utilisez MeCab pour extraire le nom de lieu du corps du tweet et l'extraire de l'API Yahoo! est utilisé pour convertir en informations de latitude et de longitude, et ce contenu est également affiché. La première moitié est de savoir comment coder le traitement des données, et la seconde moitié est de voir le résultat de la visualisation et de la visualisation, donc si vous voulez voir ce qui se passe en images, c'est Veuillez consulter [À propos de la moitié inférieure](http://qiita.com/kenmatsu4/items/114f3cff815aa5037535#2- Visualisation des informations de localisation) sur la page.
Tout d'abord, importez les bibliothèques à utiliser et établissez une connexion à mongoDB.
%matplotlib inline
import numpy as np
import json, requests, pymongo, re
from pymongo import Connection
from collections import defaultdict
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
connect = Connection('localhost', 27017)
db = connect.starbucks
tweetdata = db.tweetdata
location_dict = db.location
Les informations du tweet elles-mêmes contiennent un champ appelé «coordonnées», et si vous tweetez avec des informations de localisation telles que le GPS, la latitude et la longitude seront incluses ici. Voyons d'abord combien de personnes tweetent avec des informations de localisation.
num_not_geo = tweetdata.find({'coordinates':None,'spam':None,'retweeted_status': None},{'_id':1, 'coordinates':1}).count()
num_geo = tweetdata.find({'coordinates':{"$ne":None},'spam':None,'retweeted_status': None},{'_id':1, 'coordinates':1}).count()
print "num_not_geo",num_not_geo
print "num_geo", num_geo
print "%.3f"%(num_geo / float(num_geo+num_not_geo) * 100),"%"
** <<< Résultat >>> **
@ arieee0's "Introduction de la méthode d'estimation de la position de l'utilisateur SNS à partir d'un exemple de texte et d'application" Dans le cas de p24, le ratio de Tweet avec informations de position est de 0,3% C'est pourquoi les amateurs de staba peuvent avoir tendance à insister un peu w (bien que je ne puisse pas le dire à moins de tester pour voir si la différence est significative).
Je cherchais des informations géographiques à partir du corps du tweet, mais j'ai trouvé que MeCab peut extraire le nom du lieu en premier lieu, donc je vais l'utiliser. Comme c'est pratique! Voici un exemple d'analyse morphologique avec MeCab, qui se trouve dans Roppongi, Shibuya et le texte, mais ceux-ci sont étiquetés comme "nomenclature appropriée, région" afin qu'ils puissent être facilement extraits: satisfait:
Nom aujourd'hui,Avocat possible,*,*,*,*,aujourd'hui,aujourd'hui,Kyo
Est un assistant,Assistance,*,*,*,*,Est,C,sensationnel
Roppongi substantif,Nomenclature propriétaire,zone,Général,*,*,Roppongi,Roppongi,Roppongi
Auxiliaire,Assistant de cas,Général,*,*,*,À,ré,ré
Aller verbe,Indépendance,*,*,Rappel à cinq étapes / ka,Forme basique,aller,Iku,Iku
Mais l'assistant,Assistant de connexion,*,*,*,*,mais,Ked,Ked
, Symbole,Point de lecture,*,*,*,*,、,、,、
Cet accessoire,*,*,*,*,*,Cette,Donc non,Donc non
Pré-nom,Avocat possible,*,*,*,*,Avant,Mae,Mae
Auxiliaire,Assistant de cas,Général,*,*,*,À,ré,ré
Shibuya substantif,Nomenclature propriétaire,zone,Général,*,*,Shibuya,Shibuya,Shibuya
Auxiliaire,Assistant de cas,Général,*,*,*,À,ré,ré
Aller verbe,Indépendance,*,*,Rappel à cinq étapes / ka,Type continu,aller,Iki,Iki
Verbe assistant Tai,*,*,*,Spécial Thaïlande,Forme basique,Vouloir,Thaïlande,Thaïlande
.. symbole,Phrase,*,*,*,*,。,。,。
Puisque la nomenclature a déjà été extraite avec MeCab et placée dans la base de données, le nom de lieu est extrait d'ici et placé dans un autre champ.
#Extraire le nom de la zone du texte avec Mecab et champ: location_Définir comme nom
def location_name_mecab(sentence):
t = mc.Tagger('-Ochasen -d /usr/local/Cellar/mecab/0.996/lib/mecab/dic/mecab-ipadic-neologd/')
sentence = sentence.replace('\n', ' ')
text = sentence.encode('utf-8')
node = t.parseToNode(text)
result_dict = defaultdict(list)
for i in range(140):
if node.surface != "": #Exclure les en-têtes et les pieds de page
#Sélectionnez une nomenclature appropriée et un mot local
if (node.feature.split(",")[1] == "Nomenclature propriétaire") and (node.feature.split(",")[2] == "zone"):
plain_word = node.feature.split(",")[6]
if plain_word !="*":
result_dict[u'Nom de la zone'].append(plain_word.decode('utf-8'))
node = node.next
if node is None:
break
return result_dict
for d in tweetdata.find({'spam':None},{'_id':1, 'text':1}):
ret = location_name_mecab(d['text'])
tweetdata.update({'_id' : d['_id']},{'$push': {'location_name':{'$each':ret[u'Nom de la zone']}}})
Maintenant que le nom du lieu a été extrait, nous allons acquérir les informations de latitude et de longitude en fonction de celui-ci. J'utilise l'API Yahoo! Geocoder, mais chaque fois que j'accède, cela consomme le nombre de fois et je reste coincé dans la limite d'accès, alors je choisis d'abord le nom de lieu à convertir et j'ai un ensemble de nom de lieu, de latitude et de longitude. Sera amené à mongoDB.
Commencez par créer une liste de noms de lieux pour lesquels vous souhaitez obtenir des informations de latitude et de longitude.
#Emplacement du Tweet_Rendre le nom unique et l'objet dictionnaire"loc_name_dict"Agréger à
loc_name_dict = defaultdict(int)
for d in tweetdata.find({'spam':None},{'_id':1, 'location_name':1}):
for name in d['location_name']:
loc_name_dict[name] += 1
Lancez l'ensemble agrégé de noms de lieux dans Yahoo! Geocoder API pour obtenir des informations de latitude et de longitude. Comme appid est requis pour utiliser l'API de géocodeur, créez un compte sur Yahoo! Developer Network, obtenez l'appid et définissez-le.
#Ajoutez la latitude et la longitude au nom de lieu extrait du tweet et importez-le dans mongoDB
def get_coordinate_from_location(location_name):
payload = {'appid': '<Définir Yahoo appid>', 'output':'json'} #Définissez l'appid sur celui de votre compte!
payload['query'] = location_name # eg.g u'Roppongi'
url = "http://geo.search.olp.yahooapis.jp/OpenLocalPlatform/V1/geoCoder"
r = requests.get(url, params=payload)
if r.status_code == 200:
jdata = json.loads(r.content)
#Calculez la moyenne à partir de la liste des informations de localisation obtenues par la requête et utilisez-la comme latitude et longitude du nom de lieu.
try:
ret = np.array([map(float,j['Geometry']['Coordinates'].split(',')) for j in jdata['Feature']])
except KeyError, e:
"KeyError(%s)" % str(e)
return []
return np.average(ret,axis=0)
else:
print "%d: error." % r.status_code
return []
#Nom du lieu-Une table qui contient des liens pour la latitude et la longitude"location"Mettre en
for name in loc_name_dict.keys():
loc = get_coordinate_from_location(name)
if len(loc) > 0:
location_dict.insert({"word":name,"latitude":loc[1],"longitude":loc[0]})
Maintenant que le nom du lieu et la latitude / longitude ont été liés, nous l'appliquerons aux données du Tweet. Les noms de lieux katakana expriment souvent des noms de pays, etc., et il y avait peu de cas où ils étaient exprimés comme leur propre lieu, de sorte que les noms de lieux ne contenant que du katakana étaient exclus. En outre, il existe une zone appelée Shinkaihotsu dans la ville d'Izumi, dans la préfecture de Toyama, mais elle a également été exclue à titre d'exception car elle était utilisée dans un sens différent dans de nombreux cas. (C'est un nom de lieu rare) De plus, "Japon" est très vague, donc je l'exclus.
#Ajouter des informations de position du texte aux données de Tweet
#Extraire le nom de lieu et la latitude / longitude de la base de données et les conserver dans l'objet dictionnaire
loc_dict = {loc['word']:[loc['longitude'],loc['latitude']] for loc in location_dict.find({})}
def get_coord(loc_name):
#Excluez les noms de lieux uniquement en Katakana (car il existe de nombreux noms de pays et il est peu probable qu'ils représentent l'emplacement)
regex = u'^[UNE-Vers le bas]*$'
match = re.search(regex, loc_name, re.U)
if match:
return 0
#Mots exclus (car le nouveau développement est un nom de lieu pour une raison quelconque et le Japon est trop vague mais fréquent)
if loc_name in [u'Nouveau développement', u'Japon']:
return 0
if loc_name in loc_dict:
#Si tel est le cas, renvoyez les informations de localisation
return (loc_dict[loc_name][0],loc_dict[loc_name][1])
else:
#Sinon, renvoie zéro
return 0
def exist_check(word):
return True if word in loc_dict else False
for d in tweetdata.find({'coordinates':None,'spam':None},{'_id':1, 'location_name':1}):
if len(d['location_name']) > 0:
name_list = np.array(d['location_name'])
#Vrai s'il y a des informations de localisation,Sinon, génération de fausses séquences
ind = np.array(map(exist_check, name_list))
#Nombre réel
T_num = len(ind[ind==True])
#Traitez uniquement les Tweets avec des noms de lieux
if T_num > 0:
coordRet = map(get_coord, name_list[ind]) # key_list[ind]Est uniquement pour ceux qui ont des informations de localisation
[coordRet.remove(0) for i in range(coordRet.count(0))] #Supprimer 0
if len(coordRet) == 0:
continue
#Adoptez le premier nom de lieu (il y a des cas où plusieurs noms de lieu sont dans le Tweet, mais la première place est plus importante)
lon, lat = coordRet[0]
#Reflété dans DB
tweetdata.update({'_id' : d['_id']},
{'$set' : {'text_coord' : {'longitude':lon, 'latitude': lat}}})
Maintenant que nous avons toutes les données, j'aimerais les visualiser. Tout d'abord, je vais enfin comploter sans penser à rien.
#Extraction des informations de latitude et de longitude incluses dans les tweets
loc_data = np.array([[d['coordinates']['coordinates'][1],d['coordinates']['coordinates'][0]]\
for d in tweetdata.find({'coordinates':{"$ne":None},'spam':None},{'_id':1, 'coordinates':1})])
#Extraire la liste des informations d'emplacement d'extraction de tweet de la base de données
text_coord = np.array([[d['text_coord']['latitude'],d['text_coord']['longitude']] for d in tweetdata.find({'text_coord':{'$ne':None}},{'_id':1, 'text_coord':1})])
lat1 = loc_data[:,0] #latitude(latitude)
lon1 = loc_data[:,1] #longitude(longitude)
lat2 = text_coord[:,0] #latitude(latitude)
lon2 = text_coord[:,1] #longitude(longitude)
xlim_min = [np.min(lon)*.9,120,139]
xlim_max = [np.max(lon)*1.1,150,140.5]
ylim_min = [np.min(lat)*.9,20,35.1]
ylim_max = [np.max(lat)*1.1,50,36.1]
for x1,x2,y1,y2 in zip(xlim_min,xlim_max,ylim_min,ylim_max):
plt.figure(figsize=(10,10))
plt.xlim(x1,x2)
plt.ylim(y1,y2)
plt.scatter(lon1, lat1, s=20, alpha=0.4, c='b')
for x1,x2,y1,y2 in zip(xlim_min,xlim_max,ylim_min,ylim_max):
plt.figure(figsize=(10,10))
plt.xlim(x1,x2)
plt.ylim(y1,y2)
plt.scatter(lon2, lat2, s=20, alpha=0.4, c='g')
Commençons par les données du Tweet qui contiennent à l'origine la latitude et la longitude.
Et ça? Je ne suis pas sûr.
Cependant, comme vous l'avez peut-être remarqué, il y a des taches dans le coin supérieur droit.
Je voudrais l'élargir un peu.
C'est le Japon! : sourire:
Puisque le mot recherché est «staba», c'est naturel, mais le fait que l'archipel japonais puisse être identifié à environ 1%, 5 000 tweets signifie que les personnes qui tweetent avec «staba» sont uniformément réparties. On peut dire qu'il y en a.
Maintenant, je voudrais mettre ces données sur la carte et les voir plus clairement.
Nous utiliserons une bibliothèque appelée Matplotlib basemap, donc installez la bibliothèque en vous référant à ce lien.
#Tracer sur la carte
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
#ite = 20
ar = np.arange
enlarge = [1,2,4,8,16,32]
w_list = [15000000./(i) for i in enlarge]
h_list = [9000000./(i) for i in enlarge]
xlim_min = [-142, 80, 120, 135, 139]#[3:5]
xlim_max = [ 192, 160, 150, 142, 141]#[3:5]
ylim_min = [ -55, 0, 20, 33, 35]#[3:5]
ylim_max = [ 75, 50, 50, 37, 36.2]#[3:5]
ss = [ 0.7, 0.3, 0.1, 0.03, 0.005]#[3:5]
for lon, lat in zip([lon1,lon2],[lat1,lat2]):
for i, s in zip(ar(len(xlim_min)),ss):
m = Basemap(projection='merc',llcrnrlat=ylim_min[i] ,urcrnrlat=ylim_max[i] ,\
llcrnrlon=xlim_min[i],urcrnrlon=xlim_max[i] ,lat_ts=20, resolution='c')
plt.figure(figsize=(13,13))
m.bluemarble()
if i > 2:
m.drawcoastlines(linewidth=0.25)
for x, y in zip(lon,lat):
m.tissot(x, y, s,100,facecolor='red',zorder=100,alpha=0.4)
plt.show()
plt.savefig('plot_map_%s.png'%(str(i)))
Eh bien, c'est le résultat.
Si vous le mettez sur la carte, vous pouvez voir d'un coup d'œil de quelle zone vous tweetez.
Depuis que je recherche "staba", il y en a beaucoup au Japon, mais étonnamment, des tweets "staba" sont également créés à partir de diverses régions telles que l'Europe, les États-Unis et l'Asie du Sud-Est!
Aussi, je vais l'élargir.
Il remplit le Japon w Vous pouvez voir après le tweet ici et là à Taiwan, en Chine, en Corée du Sud et en Asie du Sud-Est.
Développez encore.
Bien qu'il soit dispersé un peu partout, Tomeihan est toujours particulièrement bondé.
Après tout, il y en a beaucoup dans les zones urbaines où la population semble importante et qui n'a pas été tweetée depuis les zones montagneuses.
C'est celui qui s'est concentré sur la zone métropolitaine avec le plus fort grossissement. La partie blanchâtre est la partie plaine, mais il y a beaucoup de tweets d'ici, et elle n'est pas tweetée depuis la partie verte de la montagne. N'est-ce pas en quelque sorte conforme à l'intuition?
Les informations de latitude et de longitude qui peuvent être déduites du texte sont ** 50 310 **, soit près de 10 fois plus que les données GPS précédentes. Étant donné que le processus de traçage de la latitude et de la longitude estimées à partir du corps du tweet avec le code précédent est déjà inclus, nous examinerons à nouveau la carte.
J'ai hâte de voir à quoi ressemblera l'intrigue d'après le nom du lieu dans le corps du tweet.
Cette fois, je suis complètement concentré sur le Japon. Parce que les noms de lieux en japonais sont extraits par MeCab et que les noms de lieux Katakana sont exclus comme mentionné ci-dessus, je pense que le résultat peut être considéré comme attendu.
Agrandir.
C'est plus serré qu'avant! Hokkaido est moins dense, mais Honshu, Shikoku et Kyushu semblent assez denses. Lors de la conversion d'un nom de lieu en latitude et longitude, un nom de lieu mystérieux a été inclus, ou un point au milieu de la mer a également été inclus, donc je pense que les informations GPS sont imbattables en termes de précision. De plus, comme le nom de lieu dans le corps du tweet n'indique pas toujours la position actuelle, je pense que la précision s'améliorera si une méthode permettant de deviner comment le nom de lieu est utilisé dans la phrase à partir des mots environnants peut être prise, alors j'aimerais en faire un problème. Je vais.
Agrandir.
Cela dit, c'est dispersé de manière sympa!
Enfin, la zone métropolitaine à nouveau.
D'une manière ou d'une autre, le nombre semble être inférieur à celui des informations GPS, car la latitude et la longitude sont obtenues à partir du nom du lieu, elles sont donc agrégées au même point. Vous pouvez voir des points orange foncé, ce qui signifie que de nombreux points sont rassemblés au même endroit.
Donc, cette fois, j'ai pris les informations de position des données du Tweet et les ai visualisées.
Quel est le contenu de marmonner "Staba" à l'étranger? Il y a certaines choses qui m'intéressent, mais cela fait longtemps, alors j'écrirai les résultats de l'analyse dans le prochain épisode.
Le code complet peut être trouvé sur Gist.
Recommended Posts