Pythonでmatplotlib
データフレームからpandas
を使用して一連の散布図を作成する最良の方法は何ですか?
たとえば、興味のある列を持つデータフレームdf
がある場合、通常はすべてを配列に変換します。
import matplotlib.pylab as plt
# df is a DataFrame: fetch col1 and col2
# and drop na rows if any of the columns are NA
mydata = df[["col1", "col2"]].dropna(how="any")
# Now plot with matplotlib
vals = mydata.values
plt.scatter(vals[:, 0], vals[:, 1])
プロットする前にすべてを配列に変換する際の問題は、データフレームから抜け出すことを余儀なくされることです。
プロットに完全なデータフレームを持つことが不可欠である次の2つのユースケースを検討してください。
たとえば、scatter
の呼び出しでプロットした対応する値のcol3
のすべての値を調べ、その値で各ポイント(またはサイズ)を色付けする場合はどうでしょうか。戻って、col1,col2
のna以外の値を引き出し、対応する値を確認する必要があります。
データフレームを保持しながらプロットする方法はありますか?例えば:
mydata = df.dropna(how="any", subset=["col1", "col2"])
# plot a scatter of col1 by col2, with sizes according to col3
scatter(mydata(["col1", "col2"]), s=mydata["col3"])
同様に、列の一部の値に応じて、各ポイントを異なる方法でフィルタリングまたは色付けしたいと考えてください。例えば。 col1, col2
で特定のカットオフを満たすポイントのラベル(ラベルがdfの別の列に格納されている場所)に自動的にプロットする場合、またはデータフレームで行うようにこれらのポイントに異なる色を付ける場合Rの例:
mydata = df.dropna(how="any", subset=["col1", "col2"])
myscatter = scatter(mydata[["col1", "col2"]], s=1)
# Plot in red, with smaller size, all the points that
# have a col2 value greater than 0.5
myscatter.replot(mydata["col2"] > 0.5, color="red", s=0.5)
これをどのように行うことができますか?
EDIT crewbumへの返信:
最良の方法は、各条件(subset_a
、subset_b
など)を個別にプロットすることです。あなたが多くの条件を持っている場合、例えば散布図を4種類以上のポイントに分割し、それぞれを異なる形状/色でプロットします。条件a、b、cなどをエレガントに適用し、最後のステップとして「残り」(これらの条件のいずれにも当てはまらないもの)をプロットするにはどうすればよいでしょうか。
同様に、col1,col2
に基づいてcol3
を異なる方法でプロットする例では、col1,col2,col3
間の関連付けを壊すNA値があるとどうなりますか?たとえば、col2
値に基づいてすべてのcol3
値をプロットしたいが、一部の行にcol1
またはcol3
のいずれかでNA値がある場合、dropna
を使用する必要があります。最初。だからあなたがするだろう:
mydata = df.dropna(how="any", subset=["col1", "col2", "col3")
次に、mydata
を使用してプロットすることができます。col1,col2
の値を使用して、col3
間の散布図をプロットします。しかし、mydata
にはcol1,col2
の値を持つがcol3
のNAであるいくつかのポイントが欠落し、それらはまだプロットする必要があります...すなわち、フィルタリングされたセットmydata
?内のnotであるポイント
以下の例のように、numpy配列として抽出するのではなく、DataFrame
の列を直接matplotlibに渡してみてください。
df = pd.DataFrame(np.random.randn(10,2), columns=['col1','col2'])
df['col3'] = np.arange(len(df))**2 * 100 + 100
In [5]: df
Out[5]:
col1 col2 col3
0 -1.000075 -0.759910 100
1 0.510382 0.972615 200
2 1.872067 -0.731010 500
3 0.131612 1.075142 1000
4 1.497820 0.237024 1700
plt.scatter(df.col1, df.col2, s=df.col3)
# OR (with pandas 0.13 and up)
df.plot(kind='scatter', x='col1', y='col2', s=df.col3)
colors = np.where(df.col3 > 300, 'r', 'k')
plt.scatter(df.col1, df.col2, s=120, c=colors)
# OR (with pandas 0.13 and up)
df.plot(kind='scatter', x='col1', y='col2', s=120, c=colors)
ただし、凡例を使用して散布図を作成する最も簡単な方法は、ポイントタイプごとにplt.scatter
を1回呼び出すことです。
cond = df.col3 > 300
subset_a = df[cond].dropna()
subset_b = df[~cond].dropna()
plt.scatter(subset_a.col1, subset_a.col2, s=120, c='b', label='col3 > 300')
plt.scatter(subset_b.col1, subset_b.col2, s=60, c='r', label='col3 <= 300')
plt.legend()
私が知ることができることから、matplotlibは単純にNA x/y座標またはNAスタイル設定(たとえば、色/サイズ)を持つポイントをスキップします。 NAのためにスキップされたポイントを見つけるには、isnull
メソッドを試してください:df[df.col3.isnull()]
ポイントのリストを多くのタイプに分割するには、 numpy select
を見てください。これは、ベクトル化されたif-then-else実装であり、オプションのデフォルト値を受け入れます。例えば:
df['subset'] = np.select([df.col3 < 150, df.col3 < 400, df.col3 < 600],
[0, 1, 2], -1)
for color, label in Zip('bgrm', [0, 1, 2, -1]):
subset = df[df.subset == label]
plt.scatter(subset.col1, subset.col2, s=120, c=color, label=str(label))
plt.legend()
Garrettのすばらしい答えに追加するものはほとんどありませんが、pandasには scatter
method もあります。それを使用すると、次のように簡単です
df = pd.DataFrame(np.random.randn(10,2), columns=['col1','col2'])
df['col3'] = np.arange(len(df))**2 * 100 + 100
df.plot.scatter('col1', 'col2', df['col3'])
データプロットのためのより強力なツールであるseaborn
を使用する代替方法を使用することをお勧めします。 seaborn scatterplot
を使用し、colum 3をhue
およびsize
として定義できます。
作業コード:
import pandas as pd
import seaborn as sns
import numpy as np
#creating sample data
sample_data={'col_name_1':np.random.Rand(20),
'col_name_2': np.random.Rand(20),'col_name_3': np.arange(20)*100}
df= pd.DataFrame(sample_data)
sns.scatterplot(x="col_name_1", y="col_name_2", data=df, hue="col_name_3",size="col_name_3")