使用Elasticsearch和Python可以轻松进行生活范围的推定

简述

我要试着写点东西,说说如果将行动历史的位置信息注册到Elasticsearch中,就可以方便地利用,并且可以很好地进行可视化的问题。

前提知識

logo-elastic.png

因为本次要使用Elasticsearch,所以简单介绍一下。
Elasticsearch是一种常与Apache Solr进行比较的全文搜索引擎。它使用无模式的架构,所有的输入输出都以REST和JSON格式进行。此外,它是用Java实现的。

    詳しくはElasticsearchの紹介と特徴

安装可以通过yum或brew很容易地完成。请根据您想使用的环境自行查找。顺便一提,Elasticsearch的GUI插件elasticsearch-head非常方便,建议一起安装。

Elasticsearch的设置

一旦成功启动Elasticsearch后,我们将开始设置要使用的索引(类似于数据库中的表)的配置。
为此,首先我们将使用json格式创建索引的映射方法。
本次假设存在以下类似数据集的日志。

{
  "id":1,
  "uuid":"7ef82126c32c55f7272d5ca5dd5e40c6",
  "time":"2015-12-03T04:21:01.641Z",
  "lat":35.658546,
  "lng":139.729281,
  "accuracy":47.126048
}

为了使这种数据集能够成功映射,我们对每个字段进行了类型等设置。这次我们选择了以下设置来映射geo数据集的类型。可以想象我们正在对geo数据集进行类型映射的设置。

{
  "geo" : {
    "properties" : {
      "id" : {
        "type" : "integer"
      },
      "uuid" : {
        "type" : "string",
        "index" : "not_analyzed"
      },
      "time" : {
        "type" : "date",
        "format" : "date_time"
      },
      "location" : {
        "type" : "geo_point"
      },
      "accuracy" : {
        "type" : "double"
      }
    }
  }
}

稍作解释,uuid字段设置为not_analyzed是因为它是一个唯一的值,不希望进行词法分析处理。
此外,本次重要的是location字段的类型。geo_point是Elasticsearch提供的类型,通过设置经纬度来进行使用。通过设置该字段的类型,可以方便地进行搜索等操作。详细内容稍后会说明。

在创建了映射设置之后,可以使用它来创建索引。本次使用的索引名称是test_geo。在Elasticsearch运行的状态下,通过发送以下的curl命令即可完成创建。

curl -XPOST 'localhost:9200/test_geo' -d @geo_mapping.json

数据的注册

假设数据以日志文件的形式存储,并且我们会将数据注册到从日志文件创建的索引中。
由于这次有官方的Python客户端,我们将尝试使用它。

    公式: elasticsearch-py

这个可以很容易地通过使用pip进行安装。

pip install elasticsearch

以下是使用这个进行注册的程序的感觉。

import json
import sys
from elasticsearch import Elasticsearch

es = Elasticsearch()
index = "test_geo"
doc_type = "geo"

f = open('var/logs.json', 'r')

_line = f.readline()
while _line:
    data = json.loads(_line)
    _line = f.readline()
f.close()

for value in data:
    lat = value['lat']
    lon = value['lng']
    del value['lat']
    del value['lng']
    value.update({
        "location" : {
            "lat" : lat,
            "lon" : lon
        }
    })
    es.index(index=index, doc_type=doc_type, body=value, id=value['id'])

该程序的要点是将lat和lon合并成location,以便将其调整为适合geo_point的形式。
执行此程序后,logs.json中的行为历史信息将被注册到Elasticsearch中。非常简单。

在Kibana中进行数据可视化

数据已经注册了,剩下的就是煮或者烤了。
Kibana是一个官方提供的可视化工具,可以将数据可视化显示在Elasticsearch中注册的数据上。
目前Kibana4已经发布,建议下载最新版本试试看。
下载后,只需执行./bin/kibana命令,就可以在5601端口启动HTTP服务器。更详细的设置方法等,请参考相关文档。
实际启动后,通过任意合适的浏览器访问即可进行仪表盘的配置。
尝试调整一下,玩一下,就可以轻松地创建像下面这样的热力图等。

heatmap.png
histgram.png

生活圈估计

我已经注册了数据,所以我将尝试使用它。
这次我将尝试做这篇论文(基于移动设备位置信息的信息推荐系统)中的生活圈估计。
因为我使用了geo_type在位置信息上进行了注册,所以我可以发送这样的查询,即获取距离特定位置多少公里以内的数据。

query = {
    "from":0,
    "query": {
        "filtered" : {
            "query" : {
                "simple_query_string" : {
                    "query" : uuid,
                    "fields" : ["uuid"],
                }
            },
            "filter" : {
                "geo_distance" : {
                    "distance" : 10 + 'km',
                    "geo.location" : {
                        "lat" : lat,
                        "lon" : lon
                    }
                }
            }
        }
    }
}

实际上,利用这个方法进行生活圈估计的结果如下所示。

Stage1
35.653945 , 139.716692
半径(km): 5.90

Stage2
35.647367 , 139.709346
半径(km): 1.61

重心使う場合
35.691165 , 139.709840
半径(km): 8.22

昼: (104)
35.696822 , 139.708228
半径(km): 9.61
夜: (97)
35.685100 , 139.711568
半径(km): 6.77

最寄り駅(昼): 東新宿
最寄り駅(夜): 新宿御苑前

印象

Elasticsearch非常容易设置,而且使用也很简单。
Elasticsearch真厉害。Kibana也很厉害。而且好像还有个新产品(Beats)。
根据数据量的大小,先试着将数据注册到Elasticsearch,有很多便利之处。
日志之类的东西可以用fluentd等自动注册,所以结合起来可以做很多事情。

写文章真难…

bannerAds