謎の生物


概要

ツイッターに投稿している謎の生物についてまとめました。
https://twitter.com/graph_gorilla

仕組み

1.乱数を出力
  謎の生物は正規乱数で作っています。全体に分布させるときは一様乱数を使っています。
  謎の生物の座標を指定して生成する場合はrand_norm関数、
  全体をうにょうにょさせる場合はrand_uni関数、
  ランダムに動かすにはmove_random関数を使用します。

2. 配列に格納
  x座標用の配列dfxとy座標用の配列dfxを用意します。
  出力する乱数は全てこの配列に格納します。

3.seabornのkdeplotでプロット
  2で格納した配列を少しずつスライドさせながらプロットしていきます。
  変数sが配列の最初の位置です。s~s+1000の区間がプロットに使用するデータになります。
  プロットするたびに100ずつ足すことで、配列を読み込む位置が100ずつずれていきます。  

4.gif画像として保存
  下のリンクのやり方を参考にしました。imagemagickというパッケージが必要らしいです。

test.py
import random
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import seaborn as sns

#ロジスティック関数
def logi(x,a):
    return 1 / (1 + np.exp(-x+a))

#反転ロジスティック関数
def revlogi(x,a):
    return 1-(1 / (1 + np.exp(-x+a)))

#壁
def wall(x,r):
    lx9=logi(x,90)
    lr9=logi(r,0)
    lx1=revlogi(x,10)
    lr1=revlogi(r,0)
    result=lx9*lr9+lx1*lr1
    return 1-result

frame_count=0   #フレームカウント用変数
colname="Blues"     #ヒートマップの色

#初期設定
fig=plt.figure(figsize=(7,7))
sns.set_style({"axes.facecolor": plt.get_cmap(colname)(15)})

#乱数格納用配列
dfx = []
dfy = []

x=20    #xの位置
y=20    #yの位置

#正規乱数生成(謎の生物)
def rand_norm(xx,yy,sdx,sdy,n): # (x座標, y座標 , x方向の標準偏差, y方向の標準偏差, 繰り返し数)
    global frame_count,x,y
    for i in range(n):
        dfx.append(random.normalvariate(x,sdx))
        dfy.append(random.normalvariate(y,sdy))
        x=xx
        y=yy
        frame_count+=1

#一様乱数生成(全体のうにょうにょ)
def rand_uni(n):  # n: 繰り返し数
    global frame_count
    for i in range(n):
        dfx.append(random.uniform(0,100))
        dfy.append(random.uniform(0,100))
        frame_count+=1

#ランダムな動き
def move_random(n,t): #  (繰り返し数, 速さ)
    global x,y
    for i in range(n):
        rand_norm(x, y, 5, 5, t)
        randx = random.uniform(-10, 10)
        randy = random.uniform(-10, 10)
        randxx = wall(x, randx) * randx
        randyy = wall(y, randy) * randy
        x += randxx
        y += randyy

#乱数生成
#---------------------------------------------------------
#rand_norm(x座標, y座標 , x方向の標準偏差, y方向の標準偏差, 繰り返し数)
#rand_uni(繰り返し数)
#繰り返し数1000で1秒だと思います。

#move_random(繰り返し数, 速さ)
#こっちは何となくで書いているのでよくわかりません。

rand_norm(20,20,5,5,3000)
rand_norm(30,30,5,5,1000)
rand_norm(40,40,5,5,1000)
rand_norm(40,40,10,5,1000)
rand_norm(40,40,5,10,1000)
move_random(50,100)
rand_uni(3000)
rand_norm(20,20,5,5,1000)
#---------------------------------------------------------

df = pd.DataFrame({'X':dfx,'Y':dfy})    #データフレーム作成
s=0     #プロットするデータの開始位置

#プロット
def plot(data):
    global s
    plt.cla()
    plt.xlim([0, 100])
    plt.ylim([0, 100])
    plt.title(str(int(s/100))+" / "+str(int(frame_count/1000-1)*10))
    sns.kdeplot(df[s:s+1000].X,df[s:s+1000].Y,shade=True,cmap=colname)
    s+=100
    print("\b"*20,s," / ",int(frame_count/1000-1)*1000+100,end="")

#アニメーション
ani_frame_num=int(frame_count/1000-1)*10
ani = animation.FuncAnimation(fig, plot, interval=100, frames=ani_frame_num)
print("Please wait")
ani.save("plot.gif", writer="imagemagick")
print("\nFinished")

参考文献

matplotlib でアニメーションを作る
https://qiita.com/yubais/items/c95ba9ff1b23dd33fde2