Kei Minagawa's Blog

皆川圭(@keimina)のブログ、Pythonで試したことを書いていきます

Pythonで2次元データ作成ー四角形に収まる点の集合

Pythonで四角形に収まる点の集合を作成します。アルゴリズムは簡単で、ランダムに点を打ち、それが四角形の内側であれば点を残す、四角形の外側であれば点を消すを繰り返すだけです。「四角形の内側か?」を判定する関数を作成し、その関数に様々な点を与え、戻り値がTrueのときの点を集めればよいということになります。ここでは四角形は正方形ということにします。一つ目のソースコードは以下になります。

1. ライブラリを極力つかわないで書いた場合

ライブラリを極力つかわないで書くとこんな感じになるかと思います。(matplotlibは可視化のため使用)

コード1:

import random
import matplotlib.pyplot as plt

def is_inside_square(x, y):
    if 0 <= x <= 1 and 0 <= y <= 1:
        # 「xが0以上1以下の領域」かつ「yが0以上1以下の領域」すなわち点(x,y)が四角形の内側ならTrue
        return True
    else:
        # 四角形の外側ならFalse
        return False

N = 1000
for _ in range(N):
    # 点を打つ場所をランダムに決める
    x = random.random()
    y = random.random()
    # 決めた点(x, y)が三角形の内側にあればグラフに点を打つ
    if is_inside_square(x, y):
        plt.plot(x, y, color='k', marker='.')    # グラフに点を打つ

# グラフを表示する
plt.gca().set_xlim(-2,2)
plt.gca().set_ylim(-2,2)
plt.gca().set_aspect('equal')
plt.show()

f:id:keimina:20190118223908p:plain

random.random()を使用すると0から1までの少数をランダムに選んでくれます。これを利用することで、点をランダムに打つことができます。基本的には、ランダムに打った点の位置がなんらかの形状の内側にあるか、外側にあるか判定できれば、その形状を点で表すことができると思います。

2. 行数を短く書いた場合

上記コードに加え、以下の二つ目のコードも載せておきます。結果は同じです。random.random()の戻り値が[0, 1)の範囲内の値なので、四角形の内側であるかの判定は、実はこの問題では必要ないのです。またnumpyを使いfor文をなくしています。

コード2:

import numpy as np
import matplotlib.pyplot as plt

N = 1000

# ランダムに点を打つ場所を決める
x = np.random.random(N)
y = np.random.random(N)

# グラフに点を打つ
plt.plot(x, y, color='k', marker='.')

# グラフを表示する
plt.gca().set_xlim(-2,2)
plt.gca().set_ylim(-2,2)
plt.gca().set_aspect('equal')
plt.show()

3. 最終的なコード

上記のコードをみると短くはなりましたが、四角形の内側かを判定するis_inside_square関数があったほうがよいと思いました。なぜなら、関数があったほうが何をしたいのかがわかるのと、四角形ではなく三角形や他の形で同様のことをしたいときに役立つと思ったためです。

そのため最終的なコードは以下のようになりました。
コード3:

import numpy as np
import matplotlib.pyplot as plt

def is_inside_square(x, y):
    if 0 <= x <= 1 and 0 <= y <= 1:
        # 「xが0以上1以下の領域」かつ「yが0以上1以下の領域」すなわち点(x,y)が四角形の内側ならTrue
        return True
    else:
        # 四角形の外側ならFalse
        return False

# 関数をnumpy化する
is_inside_square = np.vectorize(is_inside_square)

N = 1000

# ランダムに点を打つ場所を決める
x = np.random.random(N)
y = np.random.random(N)

# 四角形の内側にある点だけを抜き出す
conditions = is_inside_square(x, y)
x = x[conditions]
y = y[conditions]

# グラフに点を打つ
plt.plot(x, y, color='k', marker='.')

# グラフを表示する
plt.gca().set_xlim(-2,2)
plt.gca().set_ylim(-2,2)
plt.gca().set_aspect('equal')
plt.show()

関数をnumpy化するのにnp.vectorizeを使用しています。

これでPythonで四角形に収まる点の集合を作成できました。同様の方法で三角形や円の内側に収まる点の集合も作成できます。

以上です。おやすみなさい。