[[FrontPage]] #contents 2015/09/13からのアクセス回数 &counter; ここで紹介したSageワークシートは、以下のURLからダウンロードできます。 http://www15191ue.sakura.ne.jp:8000/home/pub/64/ また、私の公開しているSageのサーバ(http://www15191ue.sakura.ne.jp:8000/) にユーザIDを作成することで、ダウンロードしたワークシートを アップロードし、実行したり、変更していろいろ動きを試すことができます。 ** データ処理の基礎 [#ga5e24b5] ここでは、pythonを使ってデータを取り扱う方法をまとめます。 使用するパッケージは、以下の3つです。 - ggplot: データのグラフ化パッケージ - pandas: pythonでRのデータフレームと同様の処理をするパッケージ - numpy: pythonで数値を処理する基本パッケージ sageへの入力: #pre{{ # ggplotとpandas, numpyが使えるようにインポートする from ggplot import * import numpy as np import pandas as pd }} ** なぜExcelではなく、pythonを使うのか? [#wc59528b] 自然な流れとして、「なぜExcelではなく、pythonを使うのか」という疑問が湧いてくるでしょう。 何でもできそうなExcelにも弱点があります。その大きなものは、カラム数の制限です。 大量のデータを処理するには、Excelのカラム数では不十分なのです。 ** データの取り込み [#ua5db7db] pandasパッケージでは、様々なタイプのデータを取り扱うことができます。主に以下の3つのデータの取り扱い方を説明します。 - CSVファイル: カンマで区切られたファイルで最もよく使われているデータ形式 - Excelファイル: Microsoft Excelで作られたファイル - データベース: データベース(MySQL)のテーブルやQuery結果 最初にCSVファイルを読み込む例を示します。読み込みファイルは、ローカルのファイル、 ネットワークで公開されているファイルの両方を指定することができます。 CSVのファイル読み込みには、read_csv関数を使用します。この関数の戻り値は、pandasのデータフレームです。 sageへの入力: #pre{{ # 久保本の3章のデータをネットから取り込む d = pd.read_csv('http://hosho.ees.hokudai.ac.jp/~kubo/stat/iwanamibook/fig/poisson/data3a.csv') type(d) }} #pre{{ <class 'pandas.core.frame.DataFrame'> }} *** データの素性を知る [#l66de607] 読み込んだデータがどのような物なのかその素性をしるために、info、describe関数を使用します。 info関数では、dには100個のレコードが入っており、x, y, fの3つのカラムからできており、 xが整数、yは実数、fにはオブジェクトが入っており、欠損値(null)はないことが分かります。 sageへの入力: #pre{{ # どのようなデータが入っているか調べる d.info() }} #pre{{ <class 'pandas.core.frame.DataFrame'> Int64Index: 100 entries, 0 to 99 Data columns (total 3 columns): y 100 non-null int64 x 100 non-null float64 f 100 non-null object dtypes: float64(1), int64(1), object(1) memory usage: 3.1+ KB }} このデータは、「データ解析のための統計モデリング入門」から引用しており、x, y, fは、以下の様な意味を持っています。 - \(y_i\): 個体iの種子数 - \(x_i\): 個体iのサイズ - \(f_i\): 個体iが施肥処理ならT、肥料なしならC describe関数では、各カラム毎に個数、平均、標準偏差、最小値、25%、50%、75%の値、最大値が表示されます。 sageへの入力: #pre{{ # データのばらつきを見る d.describe() }} #pre{{ y x count 100.000000 100.000000 mean 7.830000 10.089100 std 2.624881 1.008049 min 2.000000 7.190000 25% 6.000000 9.427500 50% 8.000000 10.155000 75% 10.000000 10.685000 max 15.000000 12.400000 }} 実際にdにどのような値が入っているか調べるには、最初のn個を表示するhead、最後のn個を表示するtailが便利です。 sageへの入力: #pre{{ # 最初の3個を表示してみる、最後の5個の場合には、tail(5)。個数を省略すると5個分のデータが表示される d.head(3) }} #pre{{ y x f 0 6 8.31 C 1 6 9.44 C 2 6 9.50 C }} *** 行とカラム(列)の操作 [#b189756e] pandasのデータフレームから特定のカラムや行を取り出す方法を以下に示します。 カラムの指定方法は、2通りあります。 #pre{{ データフレーム.カラム名 データフレーム['カラム名'] }} sageへの入力: #pre{{ # カラム(列)を取り出す方法 print d.y.head() print d['y'].head() }} #pre{{ 0 6 1 6 2 6 3 12 4 10 Name: y, dtype: int64 0 6 1 6 2 6 3 12 4 10 Name: y, dtype: int64 }} 特定の行を取り出す場合には、ixを使って以下の様に指定します。 #pre{{ データフレーム.ix[行番号] }} sageへの入力: #pre{{ # 行を取り出す方法 print d.ix[0] }} #pre{{ y 6 x 8.31 f C Name: 0, dtype: object }} ** データの分布を知る [#d0cd4b72] データを可視化して、データの分布をみてみましょう。データの可視化には、ggplotパッケージを使用します。 ggplotは、Rのggplot2と同様の機能をpythonで使えるようにしたもので、今も開発が進んでいます。 ggplotでの図化は、ggplot関数に表示したい図を足し込んでいきます。 以下の例では、ggplotで、データフレームとx軸要素、y軸要素を指定し、 geom_point関数で散布図を指定し、print関数で表示すると図化されます。 sageへの入力: #pre{{ # データの分布を知る # ggplotに表示したいものを足していく(直感的な図化方法) p = ggplot(d, aes(x='x', y='y')) p += geom_point() print(p) }} #pre{{ <ggplot: (8767854380393)> }} ggsave関数を使って表示された図をファイルに保存します。(sageではggsaveしないと表示されません) sageへの入力: #pre{{ # ファイルに保存して、表示(ここでは、dpi=50を指定して縮小して表示している) ggsave('fig1.png', dpi=50) }} #pre{{ Saving 11.0 x 8.0 in image. }} &ref(fig1.png); fのタイプ(C, T)別にグラフを分けて表示するのも、facet_wrap関数を足すだけでできてしまいます。 sageへの入力: #pre{{ # fの値でグラフを分けて表示する例 p = ggplot(d, aes(x='x', y='y')) p += geom_point() p += facet_wrap('f') print(p) }} #pre{{ <ggplot: (8767854380397)> }} sageへの入力: #pre{{ ggsave('fig2.png', dpi=50) }} #pre{{ Saving 11.0 x 8.0 in image. }} &ref(fig2.png); 一番よく使うのは、プロットするときにf毎に色分けする方法です。 ggplotでは、aesのcolor属性に色別に使うカラム名を指定することで、カラム毎の色分けプロットができます。 sageへの入力: #pre{{ # fの値で色を変えてプロット p = ggplot(d, aes(x='x', y='y', color='f')) p += geom_point() print(p) }} #pre{{ <ggplot: (8767854296293)> }} sageへの入力: #pre{{ ggsave('fig3.png', dpi=50) }} #pre{{ Saving 11.0 x 8.0 in image. }} &ref(fig3.png); ** データの加工 [#m3b18243] データフレームを使うとデータの加工がとても簡単にできます。 以下の様な処理も一行でできてしまいます。 - データの絞り込み - SQLのgroup byと同様な集計処理 *** データの絞り込み [#ndd9a085] データの絞り込みは、以下の形式で実行します。 #pre{{ データフレーム[絞り込み条件] }} 例として、施肥のあるものd.fがTの物だけを取り出すには、以下の様にd[d.f == 'T']とするだけです。 sageへの入力: #pre{{ # データの絞り込み # 施肥のあるもの(f=Tのもの)を取り出す d_T = d[d.f == 'T'] d_T.head() }} #pre{{ y x f 50 14 10.14 T 51 6 9.05 T 52 7 9.89 T 53 9 8.76 T 54 6 12.04 T }} sageへの入力: #pre{{ # 同様に肥料のなしのもの d_C = d[d.f == 'C'] d_C.head() }} #pre{{ y x f 0 6 8.31 C 1 6 9.44 C 2 6 9.50 C 3 12 9.07 C 4 10 10.16 C }} *** 集計処理 [#b0ecbb37] groupbyを使った集計の例として、種子数y毎の度数を計算してみましょう。 size関数を使うと、groupbyで指定されたレコードの数が返されます。 sageへの入力: #pre{{ # 肥料なしの種子数y毎の度数 d_C.groupby('y').size() }} #pre{{ y 2 1 3 2 4 3 5 4 6 10 7 1 8 5 9 8 10 9 11 4 12 3 dtype: int64 }} 集計結果をggplotのヒストグラムと比較してみましょう。 ヒストグラムの追加は、geom_histogram関数で行い、binwidth=1と指定することで、 yを幅=1で集計します。fill='grey'で塗りつぶしの色をグレイに指定しています。 sageへの入力: #pre{{ # F別のヒストグラムを表示 p = ggplot(d, aes(x='y')) p += geom_histogram(aes(binwidth=1), fill='grey') p += facet_wrap('f') print(p) }} #pre{{ <ggplot: (8767853573597)> }} sageへの入力: #pre{{ ggsave('fig4.png', dpi=50) }} #pre{{ Saving 11.0 x 8.0 in image. }} &ref(fig4.png); 集計関数の例として、y毎の平均を出してみます。これも一行で計算できます。 sageへの入力: #pre{{ # y毎のxの平均を知る d_C.groupby('y').mean() }} #pre{{ x y 2 9.430000 3 8.730000 4 9.273333 5 8.282500 6 9.945000 7 9.450000 8 10.596000 9 10.088750 10 9.745556 11 10.012500 12 10.730000 }} ** データの書き出し [#u9b91b22] pandasのデータフレームでは、データを他の形式で書き出すことができます。 - to_csv: CSVファイルに出力 - to_excel: Excel形式のファイルに出力 - to_sql: SQLを使ってデータベースに出力 例として、d_C_meanのデータフレームをExcel形式のファイルに出力してみます。 Excelでは、Excelのブック形式のファイルに複数のシートを保存することができ、データフレームはシート単位に保存されます。 最初にExcelWriterを作成し、このwriterを使ってd_C_meanを"mean"というシート名で保存します。 sageへの入力: #pre{{ # 集計結果をExcelファイルに出力する d_C_mean = d_C.groupby('y').mean() writer = pd.ExcelWriter(DATA + 'test.xls') d_C_mean.to_excel(writer, 'mean') writer.close() }} sageでは、作成されたExcelファイルtest.xlsがDATAフォルダーに保存され、 dataメニューから作成されたtest.xlsをダウンロードできます。 &ref(menu.png); ダウンロードしたtest.xlsを開くと、以下の様に表示されます。 &ref(excel.png); ** データベース連携 [#v683269b] sageには、sqliteというデータベースが入っていますが、日付の扱いが特殊なので、 ここではMySQLを使ってpandasのデータベース連携機能を説明します。 このWindows版sageには、MySQLを別途インストールしてあり、 sagedbデータベース, sageユーザもセットしてあります。 MySQLをpythonから使うには、以下のインポート文が必要です。 sageへの入力: #pre{{ # MySQLとpandaの連携 import pandas.io.sql as sql import MySQLdb }} *** データベースを使うための準備 [#vaa686b7] データベースを使うためには、データベースに接続する必要があります。 また、最後には接続conのクローズも必要です。 sageへの入力: #pre{{ # データベースを使うための準備 con = MySQLdb.connect(host='localhost', db='sagedb', user='sage', passwd='sage') cur = con.cursor() # 日本語コードのセット cur.execute("SET NAMES utf8") }} #pre{{ 0L }} *** データフレームをデータベースのテーブルに入れる [#g4d0c1a4] 先に、CSVファイルから読み込んだデータフレームdをテーブルt_dに挿入してみます。 sageへの入力: #pre{{ # データフレームdをテーブルt_dに入れる sql.write_frame(d, con=con, name='t_d', if_exists='replace', flavor='mysql') }} *** クエリーの実行 [#t801f23f] 準備ができたので、テーブルt_dから種子数y毎の頻度をSQLを使って計算してみます。 SQL文は、以下のようにします。 #pre{{ FROM t_d GROUP BY y; }} 注意する点は、count(y)などの集計されたカラムに必ず名前を付けておくことです。ここでは、cnt_yとしました。 このようにすることで、結果として返されたデータフレームresult_1で集計値を簡単に参照することができます。 sageへの入力: #pre{{ # クエリーの実行 query_1 = """ SELECT y, count(y) AS cnt_y FROM t_d GROUP BY y; """ result_1 = sql.frame_query(query_1, con) print result_1.head() print result_1.cnt_y.head() }} #pre{{ y cnt_y 0 2 1 1 3 3 2 4 5 3 5 9 4 6 20 0 1 1 3 2 5 3 9 4 20 Name: cnt_y, dtype: int64 }} sageへの入力: #pre{{ # データベースのクローズ con.close() }} ** コメント [#cb36223d] #vote(おもしろかった[2],そうでもない[0],わかりずらい[0]) #vote(おもしろかった[2],そうでもない[0],わかりずらい[1]) 皆様のご意見、ご希望をお待ちしております。 #comment_kcaptcha