生データを見て、すぐに次のようなデータ指向の観察ができる人はまずいない。
というようなデータ指向の観察ができることはほとんどありません。
gt; 店頭では、おむつとビールを一緒に買う傾向がある。
というようなデータ指向の観察ができることはほとんどありません。
また、データサイエンティストであるあなたが確かに生データを読み取ることができたとしても、投資家や上司はそうでない可能性が高いです。
データを適切に分析するためには、データを具体的かつ包括的な方法で表現する必要があります。これこそが、私たちがデータの可視化を行う理由です。
pandasライブラリは、これを実現するための様々なツールを提供しています。この記事では、棒グラフ、ヒストグラム、面積プロット、密度プロット、散布図、ブートストラッププロットなど、
pandas`の可視化ツールを使い始めるために必要なことを、順を追って説明します。
データのインポート
まず、作業やテストに使う小さなデータセットが必要です。
率直に言って、インド料理はおいしいので、インド料理のデータセットを使うことにします。Kaggle.comから無料でダウンロードできます。これをインポートするには、DataFrame
を返す read_csv()
メソッドを使います。ここに、データセットの最初の5つと最後の5つのエントリーを表示する小さなコードスニペットがあります。試しにやってみましょう。
import pandas as pd
menu = pd.read_csv('indian_food.csv')
print(menu)
このコードを実行すると、次のような結果が出力されます。
name state region ... course
0 Balu shahi West Bengal East ... dessert
1 Boondi Rajasthan West ... dessert
2 Gajar ka halwa Punjab North ... dessert
3 Ghevar Rajasthan West ... dessert
4 Gulab jamun West Bengal East ... dessert
.. ... ... ... ... ...
250 Til Pitha Assam North East ... dessert
251 Bebinca Goa West ... dessert
252 Shufta Jammu & Kashmir North ... dessert
253 Mawa Bati Madhya Pradesh Central ... dessert
254 Pinaca Goa West ... dessert
他のファイルフォーマットからデータをロードしたい場合、 pandas
は read_json()
のような同様の読み込みメソッドを提供します。変数 ingredients
が長い形式であるため、ビューは少し切り詰められた形になっています。
いくつかのカラムだけを抽出するには、角括弧でデータセットをサブセットして、注目したいカラム名を列挙します。
import pandas as pd
menu = pd.read_csv('indian_food.csv')
recepies = menu[['name', 'ingredients']]
print(recepies)
こうして得られるのは
name ingredients
0 Balu shahi Maida flour, yogurt, oil, sugar
1 Boondi Gram flour, ghee, sugar
2 Gajar ka halwa Carrots, milk, sugar, ghee, cashews, raisins
3 Ghevar Flour, ghee, kewra, milk, clarified butter, su...
4 Gulab jamun Milk powder, plain flour, baking powder, ghee,...
.. ... ...
250 Til Pitha Glutinous rice, black sesame seeds, gur
251 Bebinca Coconut milk, egg yolks, clarified butter, all...
252 Shufta Cottage cheese, dry dates, dried rose petals, ...
253 Mawa Bati Milk powder, dry fruits, arrowroot powder, all...
254 Pinaca Brown rice, fennel seeds, grated coconut, blac...
[255 rows x 2 columns]
Pandasで棒グラフをプロットする### Pandasで棒グラフをプロットする
古典的な棒グラフは読みやすく、始めるには良い場所です – それぞれの料理を作るのにかかる時間を可視化してみましょう。
Pandas は、生成されたプロットを表示するために Matplotlib エンジンに依存しています。そこで、プロットが生成された後に plt.show()
を呼び出すために、Matplotlib の PyPlot モジュールをインポートする必要があります。
まず、データをインポートしましょう。このデータセットにはたくさんの料理が含まれています。これは読みやすくするために1つの図に収まりきらないでしょう。
私たちは head()
メソッドを使って最初の 10 個の料理を取り出し、プロットに関連する変数を取り出します。すなわち、それぞれの料理の name
と cook_time
を name_and_time
という新しい DataFrame に抽出し、それを最初の 10 個の料理で切り詰めます。
import pandas as pd
import matplotlib.pyplot as plt
menu = pd.read_csv('indian_food.csv')
name_and_time = menu[['name','cook_time']].head(10)
次に、bar()
メソッドを使ってデータをプロットしてみましょう。
DataFrame.plot.bar(x=None, y=None, **kwargs)
- パラメータ
x
とy
は、X 軸と Y 軸に対応します。 -
kwargs
は、DataFrame.plot()
でドキュメント化されている追加のキーワード引数に相当します。
例えば、ラベルを回転させる rot
や、凡例を追加する legend
、 style
など、プロットをさらにカスタマイズするために多くの追加パラメータを渡すことができます…
これらの引数の多くはデフォルト値を持っており、そのほとんどはオフにされています。引数 rot
のデフォルトは 90
なので、ラベルは90度回転されます。プロットを作成するときに、これを 30 に変更しましょう。
name_and_time.plot.bar(x='name',y='cook_time', rot=30)
そして最後に、PyPlotインスタンスから show()
メソッドを呼び出してグラフを表示します。
plt.show()
これで目的の棒グラフが出力されます。
Pandasで棒グラフのX軸に複数の列をプロットする #### Pandasで棒グラフのX軸に複数の列をプロットする
しばしば、棒グラフの中の2つの変数、例えば cook_time
と prep_time
を比較したいと思うことがあります。これらはどちらも各料理に対応する変数で、直接比較することができます。
name_and_timeの DataFrame を変更して、
prep_time` も含めるようにしましょう。
name_and_time = menu[['name','prep_time','cook_time']].head(10)
name_and_time.plot.bar(x='name', rot=30)
Pandasは自動的に name
と並んでいる2つの数値が結びついていると仮定しているので、X軸の定義だけで十分です。他のDataFrameを扱う場合は、そうではないかもしれません。
もし、どの変数をプロットするかを明示的に定義する必要がある場合は、単にリストを渡せばよい。
name_and_time.plot.bar(x='name', y=['prep_time','cook_time'], rot=30)
これらの2つのコードを実行すると、以下の結果が得られます。
これは面白い。調理が早い食品ほど下ごしらえに時間がかかり、その逆もまた然りということのようです。しかし、これはかなり限定されたデータのサブセットから得られたものであり、この仮定は他のサブセットでは間違っているかもしれません。
Pandasによる積み上げ棒グラフのプロット
全体としてどの料理が一番時間がかかるか見てみましょう。準備時間と調理時間の両方を考慮したいので、それらを積み重ねることにします。
そのために、stacked
パラメータをTrue
に設定します。
name_and_time.plot.bar(x='name', stacked=True)
これで、下ごしらえと調理時間の両方を考慮して、どの料理が一番時間がかかるかを簡単に見ることができます。
Pandasで棒グラフをカスタマイズする #### Pandasで棒グラフをカスタマイズする
もし、プロットの見た目をもう少し良くしたいのであれば、 bar()
メソッドに以下のような追加の引数を渡すことができます。
-
color
–DataFrame
の各属性に対応する色を定義します。orange’、
rgbまたは
#faa005` のような rgb-code のような文字列を指定することができます。 -
title
– プロットのタイトルを表す文字列あるいはリストです。 -
grid
– グリッドを表示するかどうかを示す boolean 値です。 -
figsize
– プロットのサイズをインチ単位で表したタプル. -
legend
– 凡例が表示されるかどうかを示すブール値.
もし、横棒グラフを作成したい場合は、同じ引数を取る barh()
メソッドを利用することができます。
例えば、タイトルが "Dishes"
で、グリッドがあり、サイズが 5 x 6 インチで、凡例がある、オレンジと緑の水平棒グラフをプロットしてみましょう。
import pandas as pd
import matplotlib.pyplot as plt
menu = pd.read_csv('indian_food.csv')
name_and_time = menu[['name','cook_time','prep_time']].head()
name_and_time.plot.barh(x='name',color =['orange','green'], title = "Dishes", grid = True, figsize=(5,6), legend = True)
plt.show()
Pandasによるヒストグラムのプロット
ヒストグラムは、データの分布を示すのに便利です。あるレシピを見たとき、調理時間が平均調理時間に近いのか、それとも本当に長い時間がかかるのか、見当がつきません。平均はある程度は役に立ちますが、誤解を招いたり、大きなエラーバーが出やすいものです。
調理時間に関する多くの情報を与えてくれる分布のアイデアを得るために、ヒストグラムプロットを行いたいと思います。
Pandasでは、DataFrameに対して hist()
関数を呼び出すことで、そのヒストグラムを生成することができます。
DataFrame.hist(column=None, by=None, grid=True, xlabelsize=None, xrot=None, ylabelsize=None, yrot=None, ax=None, sharex=False, sharey=False, fcigsize=None, layout=None, bins=10, backend=None, legend=False,**kwargs)
パラメータ bins
は、使用するビンの数を指定します。
どのようなデータセットを扱う場合でも、データのクリーニングと前処理は大きな部分を占めます。今回のケースでは、いくつかの食品には適切な調理時間や準備時間が記載されていません(代わりに -1
値が記載されています)。
ヒストグラムを可視化する前に、メニューからそれらをフィルタリングしてみましょう。これは最も基本的なデータの前処理です。場合によっては、データ型を変更したり(たとえば通貨フォーマットの文字列を浮動小数点に)、他の変数に基づいて新しいデータポイントを作成したりすることもあります。
無効な値をフィルタリングし、X軸に50ビンのヒストグラムを表示してみましょう。
import pandas as pd
import matplotlib.pyplot as plt
menu = pd.read_csv('indian_food.csv')
menu = menu[menu.cook_time != -1] # Filtering
cook_time = menu['cook_time']
cook_time.plot.hist(bins = 50)
plt.legend()
plt.show()
この結果、次のようになります。
Y 軸では料理の頻度を、X 軸では料理にかかる時間を見ることができます。
棒グラフが高いほど、頻度が高いことを意味します。このヒストグラムによると、ほとんどの料理は調理に0〜80分かかっています。このヒストグラムによると、ほとんどの料理は 0 ~ 80 分の間で調理され、最も高い数値は本当に高いバーにあります。
とりあえず、ビンの数を変更して、ヒストグラムにどのような影響を与えるか見てみましょう。その後、目盛りの頻度を変更します。
ビンの大きさでデータを強調する
このヒストグラムを「10」ビンでプロットしてみましょう。
import pandas as pd
import matplotlib.pyplot as plt
menu = pd.read_csv('indian_food.csv')
menu = menu[menu.cook_time != -1] # Filtering
cook_time = menu['cook_time']
cook_time.plot.hist(bins = 10)
plt.legend()
plt.show()
これで、X軸全体が10ビンになりました。3つのビンだけがデータの頻度を持ち、残りのビンは空であることに注意してください。
ここで、ビンの数を増やしてみましょう。
import pandas as pd
import matplotlib.pyplot as plt
menu = pd.read_csv('indian_food.csv')
menu = menu[menu.cook_time != -1] # Filtering
cook_time = menu['cook_time']
cook_time.plot.hist(bins = 100)
plt.legend()
plt.show()
今度は、ビンが不格好に離れて配置され、このためにまたいくつかの情報が失われています。ビンの大きさは、常に実験して、調べたいデータがきれいに表示されるまで調整したいものです。
デフォルトの設定(ビン番号のデフォルトは10)では、この場合、ビン番号が奇数になってしまいます。
Pandas ヒストグラムのティックフリークエンシーの変更
これらのプロットを表示するエンジンとして Matplotlib を使用しているので、任意の Matplotlib カスタマイズ技術も使用できます。
X 軸の刻みの頻度が少し低いので、0から
cook_time.max()` までの 20 ステップ刻みの整数の配列を作成し、最も大きな数値を持つエントリを返します。
また、プロットには多くの刻みが含まれるので、うまく収まるように45度回転させます。
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# Clean data and extract what we're looking for
menu = pd.read_csv('indian_food.csv')
menu = menu[menu.cook_time != -1] # Filtering
cook_time = menu['cook_time']
# Construct histogram plot with 50 bins
cook_time.plot.hist(bins=50)
# Modify X-Axis ticks
plt.xticks(np.arange(0, cook_time.max(), 20))
plt.xticks(rotation = 45)
plt.legend()
plt.show()
この結果、次のようになります。
複数のヒストグラムをプロットする
今度は、プリパレーションタイムをミックスに追加してみましょう。このヒストグラムを追加するために、両方を 60% の不透明度に設定した別々のヒストグラムとしてプロットします。
Y軸とX軸を共有するので、重なり合うことになります。少し透明にしておかないと、2番目にプロットしたヒストグラムの下にあるヒストグラムが見えないかもしれません。
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# Filtering and cleaning
menu = pd.read_csv('indian_food.csv')
menu = menu[(menu.cook_time!=-1) & (menu.prep_time!=-1)]
# Extracting relevant data
cook_time = menu['cook_time']
prep_time = menu['prep_time']
# Alpha indicates the opacity from 0..1
prep_time.plot.hist(alpha = 0.6 , bins = 50)
cook_time.plot.hist(alpha = 0.6, bins = 50)
plt.xticks(np.arange(0, cook_time.max(), 20))
plt.xticks(rotation = 45)
plt.legend()
plt.show()
この結果
ほとんどの料理は1時間以内、もしくは1時間程度で作ることができると結論づけられます。しかし、下ごしらえに10時間、調理に長時間を要するなど、準備に2、3日かかるものも少なくありません。
ヒストグラムのカスタマイズ プロット
ヒストグラムをカスタマイズするには、棒グラフで使用したのと同じキーワード引数を使用できます。
例えば、タイトル、グリッド、凡例、7×7 インチのサイズで、緑と赤のヒストグラムを作成してみましょう。
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
menu = pd.read_csv('indian_food.csv')
menu = menu[(menu.cook_time!=-1) & (menu.prep_time!=-1)] #filltering
cook_time = menu['cook_time']
prep_time = menu['prep_time']
prep_time.plot.hist(alpha = 0.6 , color = 'green', title = 'Cooking time', grid = True, bins = 50)
cook_time.plot.hist(alpha = 0.6, color = 'red', figsize = (7,7), grid = True, bins = 50)
plt.xticks(np.arange(0, cook_time.max(), 20))
plt.xticks(rotation = 45)
plt.legend()
plt.show()
そして、これがクリスマス色のヒストグラムです。
Pandasによる面積プロットの作成
面積プロットは、2つのパラメータの相関を見るときに便利です。例えば、ヒストグラムのプロットから、下ごしらえに時間がかかる料理は調理に時間がかからないという考え方に傾くのは妥当でしょう。
これを検証するために、area()
関数を用いてこの関係をプロットしてみましょう。
DataFrame.plot.area(x=None, y=None, **kwargs)
このグラフを単純化するために、調理時間の平均を下ごしらえ時間でグループ分けして使ってみましょう。
time = menu.groupby('prep_time').mean()
この結果、新しいDataFrameが生成されます。
prep_time
5 20.937500
10 40.918367
12 40.000000
15 36.909091
20 36.500000
...
495 40.000000
500 120.000000
さて、出来上がった「時間」DataFrameで面積プロットをします。
import pandas as pd
import matplotlib.pyplot as plt
menu = pd.read_csv('indian_food.csv')
menu = menu[(menu.cook_time!=-1) & (menu.prep_time!=-1)]
# Simplifying the graph
time = menu.groupby('prep_time').mean()
time.plot.area()
plt.legend()
plt.show()
ここで、下ごしらえ時間と調理時間の間の相関の概念が崩れました。他のグラフタイプでは、ある結論を導くかもしれませんが、下ごしらえ時間が長いと、調理時間も長くなることを暗示する一種の相関があります。これは、私たちの仮説とは正反対です。
これは、1つのグラフ・タイプに固執するのではなく、複数のアプローチでデータセットを探索する大きな理由です。
積層面積プロットの作図
面積プロットは、棒グラフやヒストグラムと非常によく似たキーワード引数のセットを持っています。注目すべき例外が1つあります。
- 積み上げられるかどうかを示すブール値。
調理時間と下ごしらえ時間が積み重なるように、ピンクと紫で、8×9インチの大きさのグリッドで、凡例付きでプロットしてみましょう。
import pandas as pd
import matplotlib.pyplot as plt
menu = pd.read_csv('indian_food.csv')
menu = menu[(menu.cook_time!=-1) & (menu.prep_time!=-1)]
menu.plot.area()
plt.legend()
plt.show()
Pandasによる円グラフのプロット
円グラフは、比較する必要のある少数のカテゴリー値を持っているときに便利です。円グラフは非常にわかりやすく、要点がまとまっていますが、注意しなければならないことがあります。円グラフの可読性は、カテゴリ値の数がほんの少し増えるだけで、大きく損なわれてしまいます。
円グラフを描くには、次のようなシンタックスを持つ pie()
関数を使います。
DataFrame.plot.pie(**kwargs)
フレーバープロファイルをプロットする。
import pandas as pd
import matplotlib.pyplot as plt
menu = pd.read_csv('indian_food.csv')
flavors = menu[menu.flavor_profile != '-1']
flavors['flavor_profile'].value_counts().plot.pie()
plt.legend()
plt.show()
この結果は
圧倒的に辛く、甘い料理が多い。
円グラフのカスタマイズ
円グラフをより魅力的なものにするために、以前のすべてのチャートの代替で使用したのと同じキーワード引数で微調整を行うことができます。
-
shadow
– 円グラフのスライスに影があるかどうかを示すブール値です。 -
startangle
– 円グラフの開始角度。
これがどのように機能するかを示すために、料理が発生する地域をプロットしてみましょう。ここでは、スライスが多くなりすぎないように head()
を使って、最初の 10
だけを取り出します。
パイをピンク色にして、タイトルを「州」とし、影と凡例をつけて、角度を 15
から開始するようにしましょう。
import pandas as pd
import matplotlib.pyplot as plt
menu = pd.read_csv('indian_food.csv')
states = (menu[menu.state != '-1'])['state'].value_counts().head(10)
# Colors to circle through
colors = ['lightpink','pink','fuchsia','mistyrose','hotpink','deeppink','magenta']
states.plot.pie(colors = colors, shadow = True, startangle = 15, title = "States")
plt.show()
Pandasによる密度プロットの作成
統計学を学んだことがある人なら、密度プロットを見たことがあるのではないでしょうか。密度プロットは、ある範囲の値における確率密度を視覚的に表現したものです。
ヒストグラムは密度プロットであり、データ点をカテゴリーにまとめてビン化します。2番目によく使われる密度プロットはKDE (Kernel Density Estimation) プロットで、簡単に言うと、無限のビンを持つ非常に滑らかなヒストグラムのようなものです。
簡単に言えば、無限のビンを持つ非常に滑らかなヒストグラムのようなものです。これをプロットするために、 kde()
関数を使用します。
DataFrame.plot.kde(bw_method=None, ind=None, **kwargs)
例えば、調理時間をプロットしてみましょう。
import pandas as pd
import matplotlib.pyplot as plt
import scipy
menu = pd.read_csv('indian_food.csv')
time = (menu[menu.cook_time != -1])['cook_time']
time.value_counts().plot.kde()
plt.show()
この分布は次のようになります。
ヒストグラムのセクションでは、ビンを使用して関連するすべての情報とデータをキャプチャするのに苦労しました。なぜなら、データを一般化して一緒にビンにするたびに、いくつかの正確さが失われるからです。
KDEプロットでは、事実上、無限のビンを使用できる利点があります。この方法では、データが切り捨てられたり、失われたりすることはありません。
Pandasで散布図(Pair Plot)を描画する。
データを解釈するもう少し複雑な方法として、散布図行列を使用します。これは、パラメータのすべてのペアの関係を考慮する方法です。他のライブラリで作業したことがあれば、このタイプのプロットはペアプロットとして馴染みがあるかもしれません。
散布図のプロットを行うには、 pandas.plotting
モジュールから scatter_matrix()
関数をインポートする必要があります。
scatter_matrix()` 関数のシンタックスは以下のとおりです。
pandas.plotting.scatter_matrix(frame, alpha=0.5, figsize=None, ax=None, grid=False, diagonal='hist', marker='.', density_kwds=None, hist_kwds=None, range_padding=0.05, **kwargs)
複数のクラスの対の関係をグリッド上にプロットするため、グリッドのすべての対角線は、エントリーと自分自身を比較するため、廃止されます。これはデッドスペースとなるため、対角線はそのクラスの一変量分布プロットに置き換えられます。
パラメータ diagonal
には, 'kde'
または 'hist
‘ を指定すると,カーネル密度推定プロットまたはヒストグラムプロットのいずれかを利用できます.
散布図プロットを作成してみましょう.
import pandas as pd
import matplotlib.pyplot as plt
import scipy
from pandas.plotting import scatter_matrix
menu = pd.read_csv('indian_food.csv')
scatter_matrix(menu,diagonal='kde')
plt.show()
プロットはこのようになります。
Pandasでブートストラッププロットを行う ### プロット
Pandas はブートストラッププロット(Bootstrap Plot)を提供します。ブートストラッププロットとは、異なるサブサンプルサイズでいくつかの異なる統計量を計算するプロットです。そして、統計量に関する蓄積されたデータを使って、統計量自体の分布を生成します。
使い方は、pandas.plotting
モジュールから bootstrap_plot()
メソッドをインポートするのと同じくらい簡単です。bootstrap_plot()` のシンタックスは以下の通りです。
pandas.plotting.bootstrap_plot(series, fig=None, size=50, samples=500, **kwds)
そして、最後にブートストラッププロットをしてみましょう。
import pandas as pd
import matplotlib.pyplot as plt
import scipy
from pandas.plotting import bootstrap_plot
menu = pd.read_csv('indian_food.csv')
bootstrap_plot(menu['cook_time'])
plt.show()
ブートストラッププロットは次のようなものになります。
結論
I
Pythonによるデータ可視化
ビジュアライゼーションでデータをより良く理解しましょう! Matplotlib、Seaborn、Bokehなどの人気ライブラリを使って、Pythonでデータを可視化する方法を340ページで学びます。