How to | Webサイトからインポートしたデータを整理する方法
Wolfram言語の接続とデータ処理の機能は,Webサイトに表示されるデータをインポートして解析するのに理想的である.ほとんどの場合,これは比較的簡単に行うことができる.しかし,このノートブックの例に見られるように,すべてのWebサイトにおいてデータが簡単にアクセスできる形式で掲載されているわけではない.そのような場合にでもWolfram言語では,ほんの数ステップでこれらの操作を行うことができる.
アメリカ国勢調査局は,アメリカと中国の間の貿易収支についてのデータを管理している.アメリカ国勢調査局のWebサイトには,1985年から2010年にかけての月ごとのデータが示されている.
Wolfram言語では要素と呼ばれる部分のリストを見ることから始める.要素はWebサイトからインポートすることができる:
Import["http://www.census.gov/foreign-trade/balance/c5700.html", "Elements"]"Data"要素をインポートする.以下の例では,大量のデータがインポートされるので,セミコロン(;)を使って出力が制御されている.「;」を付けずにImportコマンドを評価すると,インポートされたデータがすべて表示される:
tmp = Import["http://www.census.gov/foreign-trade/balance/c5700.html", "Data"];Shortを使ってデータの一部だけを見る:
Short[tmp, 35]出力の大部分は表示されていないが,関心データがMonth,Exports,Imports,Balanceという4つの要素からなるリストに含まれていることが見て取れるであろう.したがって,4つの要素だけを含むリストを抽出することによってすべてのデータを得ることができる.データだけが確実に得られるように,最後の要素が数値である4つの要素のリストすべてを抽出する.
リストに入れた4つの下線文字と一緒にCasesを使って,4つの要素だけを持つリストを抽出する.下線文字はパターンオブジェクトであり,任意のWolfram言語式を表すことができる.最後の下線文字に?NumericQを加えることによって,4番目で最終の要素が数値であるリストだけを確実に得ることができる.Casesの最終引数として∞を使って,ネストしたリストtmpのすべてのレベル内でパターンが検索されるように指定する:
tmp1 = Cases[tmp, {_, _, _, _ ? NumericQ}, ∞];もう一度Shortを使ってデータの一部だけを見る:
Short[tmp1, 15]出力は1985年12月に始まり,1992年3月まで続くので,データの一部は返されていない.いろいろな形式がデータの表に含まれていると,このような問題がよく起る.
この場合,いくつかの入力で数字は文字列として表示されている.このためこれらの入力は,各リストの第4要素が数値でなくてはならないという必要条件に合わないとして含まれないことになる:
tmp1[[6]]Head /@ tmp1[[6]]NumberString を使って文字列に数字が含まれるかどうかをチェックすることができるが,そのためには文字列からコンマを削除する必要がある.
StringQを使って引数が文字列であるかどうかをテストし,文字列である場合にはStringReplaceを使ってコンマを空白スペースに置換する関数をまず作成する.引数が文字列ではない場合には,変更なしで返される:
f[x_] := If[StringQ[x], StringReplace[x, "," -> ""], x];引数が文字列であるかどうかをテストし,文字列である場合にはNumberStringをStringMatchQと一緒に使って文字列に数値が含まれるかどうかをテストする別の関数を作る.引数が文字列ではない場合には,関数はNumericQを使ってそれが数値であるかどうかをテストする.言い換えれば,引数が文字列であるないにかかわらず,関数の引数に数値が含まれる場合には,その関数はTrueを返す:
g[x_] := If[StringQ[x], StringMatchQ[f[x], NumberString], NumericQ[x]]その後g[x]をパターンに適用される条件付きテスト(シンボル「/;」はConditionの簡略形)で使うことができる:
tmp2 = Cases[tmp, {a_, b_ /; g[b], c_ /; g[c], d_ /; g[d]}, ∞];短くされたデータを見ると,今度はこれが1985年から2010年にまたがっていることが分かる.追加のパターンマッチングがうまく働いてすべてのデータが抽出されている.この段階では出力からコンマは削除されておらず,条件テストを適用する際にこれが削除されることに注意する:
Short[tmp2, 15]次にToExpressionを使って任意の数列をWolfram言語入力として解釈できる式に変換する関数を作成する.関数は,文字列中のコンマを空白スペースで置換することも行う:
h[x_] := If[StringQ[x], ToExpression[StringReplace[x, "," -> ""]], x];次の関数は,各リストの第1要素が年間合計を表す文字列であるか,それとも日付を表す文字列であるのかをテストする.日付の場合は,DateListに変換される:
j[x_] := If[StringMatchQ[x, "TOTAL"], x, DateList[x]]今度は上のCasesの式を取り,データの各リストの4要素それぞれに適用する置換規則を加える.Trueを返し,g[x]について条件付きである要素は,h[x]で置換され,数列から数式に変換される.各リストの第1要素はj[x]で置換され,これは任意の日付の文字列をDateListに変換する:
tmp3 = Cases[tmp, {a_, b_ /; g[b], c_ /; g[c], d_ /; g[d]} :> {j[a], h[b], h[c], h[d]}, ∞];短くされたデータを見ると,先に文字列で表された日付が今度はDateListとして表示されるようになったことが分かる.またどの数字にもコンマが付いていないことに注意する:
Short[tmp3, 15]次にDeleteCasesをパターンと一緒に第2引数として使い,データから年間合計を削除する.パターンとしてアンダースコアを2つ含むリストで"TOTAL"を使い,"TOTAL"で始まり,1つ以上のWolfram言語式の任意数列を含む任意リストをマッチさせる:
tmp4 = DeleteCases[tmp3, {"TOTAL", __}];Short[tmp4, 15]データが正しい順序になっていないことに注意する.それぞれの年ブロックは,Webサイトの表が構築さた方法のせいで,逆年代順になっている.
Sortを使ってこれを修正する:
tradeData = Sort[tmp4];Short[tradeData, 15]opts = {
Filling -> Axis,
FillingStyle -> ColorData["LakeColors"][1],
FrameLabel -> {None, "$ (× SuperscriptBox[10, -3])"},
ImageSize -> 500,
Joined -> True,
PlotRangePadding -> 0,
PlotStyle -> ColorData[2][4]
};label = TextGrid[{{Style["アメリカの中国からの月別輸入額", FontFamily -> "Arial", 12]}, {Style["出典:アメリカ国勢調査局", FontFamily -> "Arial", 9]}}];DateListPlotを使って,日付ベースのデータをプロットする:
Labeled[DateListPlot[tradeData[[All, {1, 3}]], opts], label]