Wikipediaのgeo_tagsをPythonで地理空間情報解析して遊ぶための準備

地理空間情報解析がしたい！ でもデータがない！

そんなあなたに朗報です！ なんとwikipediaは地理情報をタダで公開しています！ ただし、地理情報の準備が若干面倒臭かったのでやり方をまとめておきます。

## 最初に

[Wikipediaデータダウンロード](https://en.m.wikipedia.org/wiki/Wikipedia:Database_download)のページで詳細を見られます。書いてある内容をそのままやってみると所々ハマりどころがあります。

### 注意点

Wikipediaの記事情報はXML形式かsqlで配布されています。XMLは使いづらいのであまり好きではありません。XMLをsqlに変換するツールも配布されていますが、手間がかかることがわかったため、今回はその前段階としてsqlで配布されているものを使います。Xmlで配布されているものは10GB単位なので、下準備なく用意しても持て余します。

### license

CC-BY-SA 3.0です。詳細は[クリエイティブ・コモンズのページ](https://www.switch-science.com/catalog/list/280/)を読んでください。注意すべきはライセンスの継承ですかね。

今回利用しているwikipediaのデータは[このライセンス](https://ja.wikipedia.org/wiki/Wikipedia:%E3%82%A6%E3%82%A3%E3%82%AD%E3%83%9A%E3%83%87%E3%82%A3%E3%82%A2%E3%82%92%E4%BA%8C%E6%AC%A1%E5%88%A9%E7%94%A8%E3%81%99%E3%82%8B)のもとに公開されており、私が作成したデータや写真などもこれに準拠します。

## 位置情報geo_tagsの準備

今回はjawikiのgeo_tagsをメインに据えます。加えて、記事IDとタイトルの対応が書かれているpage_propsを利用します。

それぞれ好きな月のものをダウンロードしてください。月2回ずつダンプされているようです。

### sqlからcsvへの変換

mysqlサーバーを準備してください。

準備ができたら、

```
mysql -u user_name -p db_name < file_name.sql 
```

コマンドでデータベースにデータを取り込みます。
データベース内に入り、

```sql
SELECT * FROM table_name INTO OUTFILE 'file_name.csv' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"';
```

このコマンドでcsv出力できます。_mysqlユーザーに権限がないと書き込めないのでご注意を。columns名の出力は面倒くさいので今回はやっていません。

## pythonライブラリの準備

今回は主にpandasとgeopandasを利用します。
conda-forgeでインストールするのが一番手っ取り早いかと思います。

condaは基本的に依存パッケージを自動で解決してくれますが、地理情報系ライブラリは依存関係の解決がうまくいかないことがあるのでよしなにインストール、アップデートしてください。

## 分析準備をしよう！

geoデータをcsvで持っているgeo_tagsは、geopandas.GeoDataFrameに変換してあげる必要があります。page_propsはそのままpandas.DataFrameとして読み込みます。

読み込んだデータは、geopandas, pandas同士でmergeできます。便利。

### geo_tagsの処理

geo_tagsのjsonをcsvとして読み込んでから、地理空間情報に変換します。

```py3
import pandas as pd
import geopandas as gpd

df = pd.read_csv('geo_tags.csv', header=None) # さっき出力しなかったので、headerがありません。
df = df.loc[df[2] == 'earth'] # 火星や金星など他の星の情報が混ざっているので、除きます。カラム名は適宜読み替えてください。
geometry = [Point(xy) for xy in zip(df[4], df[5])] # 4, 5はそれぞれ緯度、経度です。
df = df.drop([4, 5], axis=1)
crs = {'init': 'epsg:4326'} # crs==座標参照系。どんな規格でgeometryを作ったかという情報
gdf = gpd.GeoDataFrame(df, crs=crs, geometry=geometry)
```

はい、これで、地理情報が完成しました。次は結合用のpageデータの処理に移ります。

### page_propsの整形

さて、先ほど作成したpage_propsのcsvですが……このままだと読めません！
私の環境のせいか一般的な問題かはわかりませんが、対処法を書いておきます。

#### unicode encoding errorの対処法

```py3
with open('xxx.csv', 'r' , encoding='utf8', errors='ignore') as f:
    # something to do
```

ファイルを読む時にエンコーディングを指定し、ignoreの引数を渡すことでエンコードがおかしい行は無視できます。

#### column数が正しくない行への対処法

```py3
df = pd.read_csv('xxx.csv', error_bad_lines=False, header=None)
```

pdで読み込む際にerror_bad_linesを無効にすれば、エラーを吐かずに無視して次の行を読んでくれます。

#### 同じIDに対し複数行に渡り情報が書かれている問題の解決

```py3
df = df[df[1].astype('str') == 'defaultsort']
```

今回は名前がほしいのでdefaultsortを取得します。

pd.DataFrameが作れたら完成です。

### 結合

それぞれの記事IDの名前を、

```py3
df.rename(columns={'before':'after'})
```

で変えておきます。今回はidに統一しました。

最後に

```py3
output = pd.merge(gdf, df, on='id', how='left')
```
![Screenshot from 2017-10-29 13-19-30.png](https://qiita-image-store.s3.amazonaws.com/0/140543/40bc0762-535c-2238-12ed-af6976d86cef.png)

こんな感じになっています。（columns名が雑ですが……）

あとは好き勝手に分析しましょう。

## まとめ

地理空間情報解析に下準備でした。

今回は文字列と結合しましたが、ぶっちゃけ文字列って相当技術力ないと役に立たないことに書いてから気が付きました！　実際にやるときには、他のデータと結合することをおすすめします。カテゴリとか面白そう。

__地理空間情報解析を楽しみましょう！__