LoginSignup
1
0

More than 3 years have passed since last update.

matplotlibでmarker="."より小さい点をプロットする

Last updated at Posted at 2020-03-19

結論

sパラメーターがマーカーサイズを設定するパラメーターです。
plt.scatter(x, y, marker=".", s=1, linewidths=0)
image.png

sパラメーターを見逃していて色々いじくり回していました。コメントでやりかたを教えていただいたのでこの記事の内容はこれで終わりです。

遺物

お恥ずかしいですが試行錯誤の履歴は残しておきます。よっぽど変なマーカーをプロットしたい時に役に立つかもしれません。

クリックして展開

要約

タイトル通り。やろうとしたらなかなか方法が見つからなかったので。
結論だけ読みたい人は 結論Axesを用いた方法
調べてたらちゃんとした方法が見つかったので更新しました 2020/03/19/21:29

前フリ

Pythonのグラフ描画ライブラリmatplotlibで散布図を描くとき、すごく細かい点をブワーッと並べたいときがありますよね。
plt.scatterのマーカーはmarkerパラメーターで指定でき、細かい点を打つときはmarker='.'とします。 ( ※matplotlib.pyplot.scatter )
しかしこの'.'のマーカー(ドキュメントのdescriptionでは「point」と呼ばれています)、これでもまだちょっと大きい気がします。

rand = lambda n:[np.random.rand() for _ in range(n)]
xy = (rand(100), rand(100))

plt.scatter(*xy, marker=".")

image.png

マーカーの枠線を消してみましょう。

plt.scatter(*xy, marker=".", linewidth=0)

image.png

若干小さくなった気がしますがこれでもまだ大きい気がします。もっとゴミみたいな点が打ちたい。

matplotlib.markers の説明を読んでみると「",":image.png:pixel」というのがあります。そうそう、ピクセル単位レベルの点が打ちたかったのです。

plt.scatter(*xy, marker=",")

image.png

どうしてこうなった……
どうやらサイズが規格化されているらしく、形を指定するとこのサイズいっぱいになるように拡大縮小されるようです。

結論 めんどくさい例

マーカーサイズの規格化を無効にするパラメーターが見つからなかったので姑息的に「規格化されても小さく見えるマーカー」を作ってみます。(直接マーカーサイズを指定できる方法をご存知のかたは教えて下さいm(_ _)m)(Axesを使った例へ)
markerパラメーターに「2次元座標のタプルの配列」を与えることで任意の多角形を描かせることができます。
これを利用して幅ゼロの対角線を引いてサイズを確保してから中心に小さく四角を作ります。

image.png (こんなん)

t = 0.1
plt.scatter(*xy, marker=[(0,0), (-1,-1), (1,1), (0,0), (t,t), (-t,t), (-t,-t), (t,-t), (t,t), (0,0)], linewidths=0)

image.png

ゴミみたいな点を打つことに成功しました!

マーカーオブジェクトを作って0~1倍の任意のサイズの点を打てるようにしてみました。

from matplotlib.markers import MarkerStyle
dot = lambda t: MarkerStyle([(0,0), (-1,-1), (1,1), (0,0), (t,t), (-t,t), (-t,-t), (t,-t), (t,t), (0,0)])
plt.scatter(*xy, marker=dot(0.2), linewidths=0)

image.png

正直もっとまともな方法あるやろ……と思われるので、まっとうな方法で小さい点を打つ方法をご存じの方はぜひご一報ください。よろしくお願いします。

Axesを用いた方法

Axes.plotではLine2Dのパラメーターを指定でき、ここにmarkersizeが存在することに気づきました。

fig, ax = plt.subplots()
ax.plot(*xy, linestyle='none', marker=',', markersize=1)

image.png

これが一番まともな方法だと思います。

ちょっとややこしいことをしようとするならやはりオブジェクト指向インターフェースを使うべきですね。
こちらの記事が参考になります。早く知っておきたかったmatplotlibの基礎知識、あるいは見た目の調整が捗るArtistの話 @skotaro さん

※小さい点でやりたかったこと

こうやって濃淡を点の密度で表現してみたかったのです。

func = lambda x,y:np.sin(x*np.pi)**2 * np.exp(-y**2/2)
n = 100
dx = 0.02
xlin = np.arange(-2,2,dx)
ylin = np.arange(-2,2,dx)
xx, yy = np.meshgrid(xlin, ylin)
pltx, plty = [], []
for x, y in zip(xx.flatten(), yy.flatten()):
    dense = func(x+dx/2, y+dx/2)
    pltx += [x+np.random.rand()*dx for _ in range(int(dense*n))]
    plty += [y+np.random.rand()*dx for _ in range(int(dense*n))]

plt.scatter(pltx, plty, s=0.01, marker='.', alpha=0.1)
plt.xlim(-2,2)
plt.ylim(-2,2)
plt.show()

image.png
(無駄にめっちゃ重いのでカラーマップにしたほうが良いと思います。)

1
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0