Python
numpy
statistics
matplotlib
pandas

データ分析と統計処理の基本的な手順の整理 (2)

More than 1 year has passed since last update.

昨日からデータ分析の基本的な手順を整理していますがその続きです。

分析のための道具を選定する

週末に開催された PyCon JP 2014 ではまだまだ Python 2 系の利用者が多いという話がありましたし Heroku の Kenneth Reitz は No Benefit なんて言っていましたが、実際のところ 2014 年現在において Python を使うなら 3.x 系だんぜん一択です。ちなみにその後の日本人の発表でも大体の人は Python 3 を推していたように思います。

Python 3 を使う理由

データ分析で Python 3 を使う理由を筆者の考えとして挙げます。

  • 文字列型のエンコーディングが Unicode を既定としている
  • Python 2 には新しい機能は追加されず、今後登場するライブラリも Python 3 ベースである

もはやこの 2 つだけでも十分でしょう。

この記事の読者もおそらく日本人が圧倒的多数でしょうし、もちろん筆者も日本人です。英語圏の人間にとっては Unicode 周りのメリットは享受しにくいでしょうが、今日において UTF-8 が既定でない言語など有り得ません。一度 Python 3 に触れれば日本人なら誰しも二度と Python 2 に戻りたくないと思うでしょう。今はインターネットで国同士の距離も無いに等しい時代、特定の地域で使いづらい言語をそのまま使うべきではありませんし、世界標準に準拠するべきです。

また Python 2 系はもはや新規機能の追加はされません。それに対し 2008 年頃から登場した pandas をはじめとする強力なライブラリはここ数年で急速に発達しており、ビッグデータブームと相まって Python をデータ分析のための強力な主要言語の地位へと向上させています。 Python 3 の登場は 2008 年ですから、それより前の資産もこの分野においては少ないか陳腐化しているでしょうから、さっさと Python 3 系に移行するべきです。移行のためのコストもそれほど大きくなるケースは無いでしょう。

データ解析三種の神器

さて MATLABR 言語のように数値解析をしようとなると、ベクトルや行列を計算することが中心となります。このときに必要となるツールをこれまた筆者の独断で三種の神器として挙げるなら次の通りです。

  • pandas (データ構造とその操作)
  • matplotlib (データの可視化)
  • IPython (対話的データ解析環境)

これも今までの記事でさんざん取り扱ってきましたから今さら追加の説明は不要でしょう。

Hadoop は本当に必要か

民間企業でビッグデータと言うとキーワードや製品名から入りすぐに Hadoop といった名前が出てくるように思います。しかし、分析の内容を考えてみて、果たしてそれが本当に必要になるでしょうか。データのサイズはもちろんのこと、その計算の性質もその都度ぜひよく考えてみてください。

MapReduceSpark は使いどころが正しければ非常に強力なツールですし、たとえば母集団からの標本抽出で使うだとか、それを Pig や Hive のような簡易的な言語でおこなうといったことが考えられますが、それにしても適用できる部分はデータ分析のフェーズの中のごく一部です。サンプルに対するデータの解析、可視化は、現代においては手元の計算機で十分ですし、その場合は Python はもちろん R やあるいは Excel などの表計算ソフトウェアでも可能です。

くれぐれも特定のソフトウェアやツールを使うことそれ自体が目的にならないようにしましょう。

サンプルコードを書く

データ分析ツールの有用性を確認するには、なにはともあれ手を動かしてコードを書いてみるのが一番です。

ファイル I/O

まず分析と言えば用意したデータをファイルから読み込むところからですね。 NumPy/SciPy にも genfromtxtloadtxt といった高水準な関数がありますが、 pandas を使えるなら基本的には read_csv のような pandas の関数を利用するのが良いでしょう。

特定の分布に従った乱数を生成する

サンプルコードを書いたり試したりするときによく使うのが乱数生成です。 NumPy/SciPy には多彩な乱数生成系が実装されていますので便利です。特に標準正規分布 (ガウシアン分布) に従い任意の平均及び分散で乱数を生成できる numpy.randam.normal は重宝します。

試しに、任意の平均及び分散を持つ標準正規分布に従う乱数から二変量を生成し、その基本統計量を求め共分散と相関係数を算出し散布図で可視化してみましょう。

# 平均 10 標準偏差 5 の標準正規分布に従う乱数を 50 個生成する
a = np.random.normal(10, 5, size=50)
# 平均 20 標準偏差 8 の標準正規分布に従う乱数を 50 個生成する
b = np.random.normal(20, 8, size=50)
# 可視化する
plt.figure()
plt.scatter(a, b)
plt.savefig("image.png")

image.png

二変量間の関係を可視化する散布図をプロットできました。

データフレームを使う

同じ事を pandas を利用してやるならこうなります。

# データフレームをつくる
df = pd.DataFrame({
    "a": np.random.normal(10, 5, size=50),
    "b": np.random.normal(20, 8, size=50)
})

# 可視化する
plt.scatter(df['a'], df['b'])

生成される画像は同一ですから省略します。

行列の参照と操作

このように pandas を使ってデータフレームを利用した場合、行列の統計算出や操作をより簡単におこなえるといったメリットがあります。

# 生成された乱数の中身を見てみる
df
#=>
#             a          b
# 0   14.104370  13.301508
# 1    9.053707  32.101631
# 2    7.731780  14.075792
# 3    8.629411  38.876371
# 4   15.604993  24.380662
# 5   13.678605  16.517300
# ... (途中省略)
# 46  12.229324  24.926788
# 47  16.650234  23.308550
# 48   8.101379  20.404972
# 49   0.807786  34.109284

# 主要な基本統計量を計算する
df.describe()
#=>
#                a          b
# count  50.000000  50.000000
# mean   10.517972  20.291032
# std     4.229104   8.104303
# min    -0.618973   4.451698
# 25%     8.006941  14.085385
# 50%    11.442714  20.018789
# 75%    13.828762  24.770515
# max    17.617583  39.991811

# 行列間の共分散を求める
df.cov()
#=>
#            a          b
# a  17.885320  -5.215284
# b  -5.215284  65.679722

# 相関係数を求める
df.corr()
#=>
#           a         b
# a  1.000000 -0.152165
# b -0.152165  1.000000

# 転置行列を求める
df.T
#=>
#           0          1          2          3          4          5   \
# a  14.104370   9.053707   7.731780   8.629411  15.604993  13.678605   
# b  13.301508  32.101631  14.075792  38.876371  24.380662  16.517300   

#           6          7          8          9     ...             40  \
# a  12.321283   3.325300   5.439189  15.693431    ...      15.220284   
# b  30.198993  24.853103  10.381890  32.567924    ...      15.801350   

#           41         42         43         44         45         46  \
# a  13.493986   6.756807   9.030604  11.044724  11.443239  12.229324   
# b  14.278252  20.388216  20.582722  25.731553  18.479491  24.926788   

#           47         48         49  
# a  16.650234   8.101379   0.807786  
# b  23.308550  20.404972  34.109284  

簡単ですね。

他の言語ではどうか

ところで余談ですが請負型受託開発を本業とした会社ですとたとえば Java での開発がメインというケースが多々あります。しかしいくら業務とはいえ、データ分析にはデータ分析に向いた言語を利用するのが一番です。

試しに上のサンプルコードで挙げた「任意の平均及び分散を持つ標準正規分布に従う乱数から二変量を生成しその基本統計量を求め共分散と相関係数を算出し散布図で可視化せよ」といった簡単な問題を R などの統計向き言語を除く他の一般的な言語で解こうとしたらたちまち難しくなってしまうことが容易にお判りかと思います。

データ分析における社会統計の 3 つのポイント

さて準備の話が少し長くなりましたが、社会統計においては調査から入手できたデータに対する一連の分析の中で大きなポイントが 3 つあります。

1. データの分布を把握する

数値の変量がどのように分布しているかはきわめて重要な前提です。分布とは変量の散らばり具合のことですが、状態を表すためにいくつかの 統計量 (statistics) が利用されます。たとえば「平均値」や「分散」などがそうです。

分布状態をとらえるためには、変数の値の分布を表形式で提示する度数分布表や、要約した統計量を可視化するための箱ひげ図などを利用します。

2. 標本から母集団の状態を推測する

次のポイントは、データの統計量に基づいて 母集団 (population) と呼ばれる全体集団の状態を推測することです。社会調査の多くは、ある集団の一部から抽出された 標本 (sample) をもとに解析をおこなうことになります。

標本は母集団の一部として取り出されたものであるため、そのデータが母集団における値を必ずしも正確に反映しているわけではなく、一定の誤差を含むことになります。標本から得られた分析結果を、それが抽出された母集団の状態として解釈するための「推測統計」の考え方と技法を身につける必要があります。推測統計では誤差から生じる確率を想定した上で、母集団における値を特定化する「推定」と、仮説を設定してそれが適合するかどうかを判定する「検定」をおこなうことになります。

3. 複数の変量の間の関連を調べる

最後に、複数の変量の間にどのような、あるいはどの程度の関連があるかを調べます。これによってどの要因が何に影響しているかの関係性を明らかにしていきます。また、データが得られた元となる母集団においても、変数と変数の間に関連があるかどうかを推測するといったこともよくおこなわれます。

まとめ

これら 3 つのポイントは、それぞれ何らかの観点に絞って、端的な指標 (= 統計量) や結論 (= 推測) として提示することを目的としています。統計分析は膨大なデータの中から、目的に応じた情報を要約した形で取り出して提示するという役割を果たします。

統計分析の手法や統計量は、事前に学ぶべき事項の積み重ねがあってはじめて理解可能であることが大半です。したがいまして闇雲に計算機にデータを放り込んで結果を見ても、その十分な知識無しには次のステップへと進むことができません。

以上の 3 つのポイントについて次回以降、手順を踏んで内容を明らかにしていきます。