XMLデータの扱い方

[2015-12-30] このページは以前のページの改訂版です。

[2016-07-06] パッケージxml2のバージョン1.0.0が出たようです。

XMLとは

XMLはExtensible Markup Language(拡張可能なマーク付け言語)の略称です。構造をもつデータを表現するための一種の言語です。

鯖江市がXMLなどを使ったオープンデータの公開を始めました:

ここではこのデータをRで読んで使う方法を解説します。

パッケージXML

鯖江市の人口XMLをWebブラウザで開いてもおそらく次のようなタグがたくさん入ったテキストとして扱われてしまうと思います。

<?xml version="1.0" encoding="UTF-8"?>
<dataroot ...>
<population>
<No>1</No>
<year>2003</year>
<age>0</age>
<man>341</man>
<fem>329</fem>
<uri>http://www3.city.sabae.fukui.jp/xml/population/#0001</uri>
</population>
……

このようなXMLをデータとして読むためのRのパッケージXMLをインストールし,読み込んでおきます:

install.packages("XML")
library(XML)

これで次のようにURLを指定してデータが読み込めます:

options(stringsAsFactors=FALSE)
df = xmlToDataFrame("http://www3.city.sabae.fukui.jp/xml/population/population.xml")

head(df) と打ち込むと,何となく読めているようです:

  No year age man fem                                                  uri
1  1 2003   0 341 329 http://www3.city.sabae.fukui.jp/xml/population/#0001
2  2 2003   1 366 374 http://www3.city.sabae.fukui.jp/xml/population/#0002
3  3 2003   2 360 367 http://www3.city.sabae.fukui.jp/xml/population/#0003
……

「男」「女」が「man」「fem」というのは何となくおかしいですね。「uri」が何を指すのかもよくわかりません。……という突っ込みはさておいて,str(df) と打ち込んで,読み込んだデータの構造を調べてみましょう。

'data.frame':	1111 obs. of  6 variables:
 $ No  : chr  "1" "2" "3" "4" ...
 $ year: chr  "2003" "2003" "2003" "2003" ...
 $ age : chr  "0" "1" "2" "3" ...
 $ man : chr  "341" "366" "360" "384" ...
 $ fem : chr  "329" "374" "367" "372" ...
 $ uri : chr  "http://www3.city.sabae.fukui.jp/xml/population/#0001" ...

ちゃんと文字列で読み込まれています。もし options(stringsAsFactors=FALSE) を最初に打ち込まなかったなら,全部factor(因子)として読み込まれてしまうでしょう。

読み込むときに,次のように列ごとに型指定をしてもかまいません:

df = xmlToDataFrame("http://www3.city.sabae.fukui.jp/xml/population/population.xml",
                    colClasses=c("integer","integer","integer",
                                 "integer","integer","character"))

望み通りの型で読めたか str(df) で確認しておきましょう。型を変更するには,

df$age = as.integer(df$age)

のようにしてもかまいません。

パッケージxml2

Hadley Wickhamの新しいパッケージxml2を使ってみましょう。このパッケージについては Parse and process XML (and HTML) with xml2 | RStudio Blog も参照してください。

install.packages("xml2")
library(xml2)
x = read_xml("http://www3.city.sabae.fukui.jp/xml/population/population.xml")
year = as.integer(xml_text(xml_find_all(x, "//year")))
age = as.integer(xml_text(xml_find_all(x, "//age")))
man = as.integer(xml_text(xml_find_all(x, "//man")))
fem = as.integer(xml_text(xml_find_all(x, "//fem")))

ここで指定した "//year" のような書き方は XML Path Language (XPath) といいます。この場合 "//year" は絶対パスで書けば "/dataroot/population/year" となりますが,略して "//year" と書くことができます。あるいは,トップレベル以外の year という意味で ".//year" と書くこともあります。

これを使ってグラフを描いてみましょう:

鯖江市の人口ピラミッドの推移
library(pyramid)
library(animation)

saveGIF({
    for (i in 2003:2013) {
        o = order(age[year==i])
        pyramids(man[year==i][o], fem[year==i][o], age[year==i][o],
                 Cstep=10, Laxis=c(0,350,700), main=i)
    }
})

xml2パッケージを使う例としては SpringerLinkでISBNから書誌情報を得る もご覧ください。


Last modified: