乙Py先生のプログラミング教室
初学者のためのプログラミング学習サイト

可視化

日本で一番有名なマークである

安産祈願マークを
プログラムで作ってみましょう!!!


動画はこちら



さて
作り方は
numpyとmatplotlibを用いて
マークを描いていきます。

widgetも用いて
うねうね変形できるようにもします。

ソースはこちら
import numpy as np
import matplotlib.pyplot as plt
from ipywidgets import interact, FloatSlider, IntSlider,Select
%matplotlib inline

r = IntSlider(min=1, max=8, step=1, value=5)
t = FloatSlider(min=1.0, max=1.5, step=0.1, value=1.0)
c = Select(options=['black', 'red', 'blue','green'],
    value='black',description='coler : ',disabled=False)

@interact(r=r,t=t,c=c)
def plot_man(r,t,c):
    plt.figure(figsize=(10,9))
    plt.axes().set_aspect('equal', 'datalim')
    
    # circle 1
    x = [np.sin(np.radians(_x))*r for _x in np.linspace(-180,180,721)]
    y = [np.cos(np.radians(_y))*r*t for _y in np.linspace(-180,180,721)]
    plt.plot(x, y, c)
    
    # circle 2
    x2 = [i*0.7 for i in x]
    y2 = [i*0.7 for i in y]
    plt.plot(x2, y2, c)
    
    # line
    x3 = [0,0]
    y3 = [min(y)*1.25,max(y)*1.25]
    plt.plot(x3, y3, c)
    
    # lines
    x4 = [i*1.2 for i in x]
    y4 = [i*1.2 for i in y]
    for i in range(16):
        x5 = [x[i*45],x4[i*45]]
        y5 = [y[i*45],y4[i*45]]
        plt.plot(x5, y5, c)
    
    plt.xlim([-20,20])
    plt.ylim([-20,20])
    plt.show()



結果はこうなります。

スクリーンショット 2019-07-28 15.47.34


rで円の半径を変更
tで楕円の倍率を変更
colorで色を変更です。

楕円は
円の縦横方向を n 倍にすることで実現しています。

なので
縦方向であれば
xの値はそのままに
yの値の倍率を変えてあげると
縦方向の楕円になります。

今回のやり方では
まず半径を決めて円を用意します。
内側の円は1つめの円の倍率を変えただけです。

縦棒はxの値が0でyの値を変化させることで
実現させ、外側の棒たちは

大きな円を用意し
1つめの円から外側の円に向かう値で
描いています。

一応16本になるみたいなので
22.5度の角度になるような計算で
座標を求めています。

全部足すと
安産マークになります!!!!!!!




せっかくなので
GIFも作ってみましょう


matplotlibではアニメーション機能で
mp4やgifも作れますが
環境によっては動かないこともあり

今回は
画像をたくさん生成して
無理くりGIFに落とし込みます。


ソースはこちら
from PIL import Image, ImageDraw, ImageFont
import numpy as np
import matplotlib.pyplot as plt
from ipywidgets import interact, FloatSlider, IntSlider,Select
import os

data_dir = 'anzan_data/'
if not os.path.exists(data_dir):
    os.makedirs(data_dir)

for a in range(30):
    plt.figure(figsize=(3,3))
    plt.axes().set_aspect('equal', 'datalim')
    plt.tick_params(labelbottom=False,
                    labelleft=False,
                    labelright=False,
                    labeltop=False)
    plt.tick_params(bottom=False,
                    left=False,
                    right=False,
                    top=False)
    plt.xlim([-20,20])
    plt.ylim([-20,20])
    c ='black'
    n = (np.abs(np.sin(a))+1)
    # circle 1
    x = [np.sin(np.radians(_x))*8 for _x in np.linspace(-180,180,721)]
    y = [np.cos(np.radians(_y))*8*n for _y in np.linspace(-180,180,721)]
    plt.plot(x, y, c)

    # circle 2
    x2 = [i*0.7 for i in x]
    y2 = [i*0.7 for i in y]
    plt.plot(x2, y2, c)

    # line
    x3 = [0,0]
    y3 = [min(y)*1.25,max(y)*1.25]
    plt.plot(x3, y3, c)

    # lines
    x4 = [i*1.2 for i in x]
    y4 = [i*1.2 for i in y]
    for i in range(16):
        x5 = [x[i*45],x4[i*45]]
        y5 = [y[i*45],y4[i*45]]
        plt.plot(x5, y5, c)
    file_name = data_dir + 'tmp_{0:02}.png'.format(a)
    plt.savefig(file_name)

images = []
for a in range(30):
    file_name = data_dir + 'tmp_{0:02}.png'.format(a)
    img = Image.open(file_name)
    images.append(img)

gif_name = 'anzan.gif'
images[0].save(gif_name,save_all=True, append_images=images[1:], optimize=False, duration=2, loop=0)





結果はこうなります。


anzan
びろんびろん動くのが
気持ちいいですよねーーーー


はい
周りのに安産祈願の方がいたら
是非送ってあげましょう!!

きっと喜ばれること
間違いなし




今回はここまでです。

それでは


 

可視化の授業には使えない

クソの役にも勃たない関数です。

動画はこちら




はーい
それでは関数の作り方をみていきましょう。


xの値からyを作る数式を元に
関数を作ります。

可視化の元となる関数は以下の通りです。
npはnumpyです。

y = np.abs(t*np.sin(x)) + ((5*np.e)**(-x**k)) * s * np.cos(x)

はい
これを上手いこと
Pythonを使って
再現していきます。

出来上がったものはコレ
import numpy as np
import matplotlib.pyplot as plt
from ipywidgets import interact, FloatSlider, IntSlider
%matplotlib inline

s = FloatSlider(min=0.8 , max=10,step=0.1,value=2.1)
t = FloatSlider(min=0.1 , max=2,step=0.1,value=0.2)
k = IntSlider(min=2,max=20,step=2,value=4)
@interact(s=s,t=t,k=k)
def plot(s,t,k):
    plt.figure(figsize=(10,9))
    x = np.arange(-3,3,0.01)
    y = np.abs(t*np.sin(x)) + ((5*np.e)**(-x**k)) * s * np.cos(x)
    plt.ylim(0,10)
    plt.xlim(-5,5)
    plt.plot(x,y)
    plt.show()

こいつを実行していただくと
出ます。!!
画像がね(汗)

ここには載せないようにしときますねーー
モザイク必要なんでwww

一応使い方としては
スクリーンショット 2019-07-27 16.05.38

S:サオ
T:タマ
K:カリ

になっているので
大きさを変えれます。

まずはTを変更してもらい
次にSで伸ばしてもらい
Kをいい感じの太さにしてくださいねーー

太くて
長くて
たくましい
・・・

まるで戦艦大和やないかーーい

はーーい
クソですねー

みなさん楽しんでくださいませ

それでは

はいどうも

また錯視です。


動画はこちら



今回は
色違いに見えるボールを
描いてみましょう。

まずはライブラリを用意します。
from PIL import Image, ImageDraw, ImageFilter

import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline

次にソースはこちら


plt.figure(figsize=(16,9))
size ,c_y,c_v = (320, 320),(255, 241, 0),(170, 68, 153)
im1,im2 = Image.new("RGB", size, color=c_y),Image.new("RGB", size, color=c_v)
dst = Image.new('RGB', (im1.width + im2.width, im1.height))
dst.paste(im1, (0, 0))
dst.paste(im2, (im1.width, 0))
draw = ImageDraw.Draw(dst)
draw.ellipse(((  30,30,290,290)),fill=(0, 127, 127), outline=None)
draw.ellipse(((350,30,610,290)),fill=(0, 127, 127), outline=None)

r = 8
for x in range(0,320,12):
    for y in range(0,320,12):
        draw.ellipse((x,y,x+r,y+r),fill=c_v, outline=None)
for x in range(320,640,12):
    for y in range(0,320,12):
        draw.ellipse((x,y,x+r,y+r),fill=c_y, outline=None)
plt.tick_params(labelbottom=False,labelleft=False,labelright=False,labeltop=False)
plt.tick_params(bottom=False,left=False,right=False,top=False)
plt.imshow(np.array(dst))
plt.show()


実行していただくと
こんな感じの画像が出力されます。

ball

右と左の大きな円は
実は同じ色なんです!!!!!!

一同「えーーー、なんだってーー」

円が
同じ色に
みえん!!

なんちってね

背景の黄色と紫
その上に乗せた緑色の円

その上に小さな円を載せると
元の円の色が明るく見えたり
暗く見えたりするので

二つの円が違って見えるんだそうな

ソースの

r = 8

を小さくしてもらうと
上に重ねた円の大きさが変わり、
大きな円の色が同じであるということが
わかっていくと思います。

試しにやってみてください

それでは。



 


どーっもーー
AKBの錯視原りのでーーっす

ということで
今回は
「錯視」をやっていきたいと思います。



動画はこちら




さて 
錯視は色々な種類があり
今回紹介するのは
同じ長さや大きさのものだけど
歪んで見える感じの画像を作成していきます。

まずは必要なライブラリの読み込みです。
from PIL import Image, ImageDraw
import matplotlib.pyplot as plt
import numpy as np

%matplotlib inline



それでは有名どころの錯視はらいってみましょうーー

ミュラー・リヤー錯視

同じ大きさの線に少し手を加えると
長く見えたり短く見えたりするやつです。
plt.figure(figsize=(20,9))
size = (800, 400)
color1,color2,width = (150, 100, 220), (200, 120, 200),5

im = Image.new("RGB", size, color=(255, 255, 255))
draw = ImageDraw.Draw(im)

x1,x2,y1,y2 = size[0]//3,size[0]//3*2,size[1]//3,size[1]//3*2

draw.line([(x1,y1),(x2,y1)] , width = width, fill = color2)
draw.line([(x1,y1),(x1-x1//3,y1-y1//3)] , width = width, fill = color1)
draw.line([(x1,y1),(x1-x1//3,y1+y1//3)] , width = width, fill = color1)
draw.line([(x2,y1),(x2+x1//3,y1-y1//3)] , width = width, fill = color1)
draw.line([(x2,y1),(x2+x1//3,y1+y1//3)] , width = width, fill = color1)
draw.line([(x1,y2),(x2,y2)] , width = width, fill = color2)
draw.line([(x1,y2),(x1+x1//3,y2-y1//3)] , width = width, fill = color1)
draw.line([(x1,y2),(x1+x1//3,y2+y1//3)] , width = width, fill = color1)
draw.line([(x2,y2),(x2-x1//3,y2-y1//3)] , width = width, fill = color1)
draw.line([(x2,y2),(x2-x1//3,y2+y1//3)] , width = width, fill = color1)

plt.tick_params(labelbottom=False,labelleft=False,labelright=False,labeltop=False)
plt.tick_params(bottom=False,left=False,right=False,top=False)
plt.imshow(np.array(im))
plt.show()

1

こんな感じで、上下の真ん中の棒の長さは一緒です。
ただ上の棒の方がやや少しだけ長く見えます。


カフェウォール錯視

横に引いた線の近くに
交互に四角を配置すると
横の線が斜めになっているように
見えるというものです。

def draw_image(im):
    draw = ImageDraw.Draw(im)
    width = im.size[0]
    box_size = width//5
    half,margin = box_size//2,0
    for j in range(5):
        margin = half//2 if j%2==0 else 0
        for i in np.array(range(5)) * box_size :
            draw.rectangle(((i+margin,j*half),(i+half+margin ,j*half+half)) , outline = None, fill = (0,0,0))
            #pass
    for j in range(1,5):
        
        draw.line([(0,j*half),(size[0],j*half+1)] , width = 3, fill = (160,160,160))
    return im

plt.figure(figsize=(20,9))
size = (800,400)
im = Image.new("RGB", size , color=(255,255,255))

im = draw_image(im)
plt.tick_params(labelbottom=False,labelleft=False,labelright=False,labeltop=False)
plt.tick_params(bottom=False,left=False,right=False,top=False)
plt.imshow(np.array(im))
plt.show()


2

横線は斜めに傾いて見えますかね?


エビング錯視

同じ大きさの円を用意して
その周囲に大きい円と小さい円を配置します。

大きい円の中の円が小さく見えて
小さい円の中の円が大きく見えるという錯視です

plt.figure(figsize=(20,9))
size = (640, 320)
im = Image.new("RGB", size, color=(255, 255, 255))

draw = ImageDraw.Draw(im)
c1,c2 = np.array([200, 160]),np.array([500, 160])
r1,r2,r3 = 30,50,15
draw.ellipse(((tuple(c1 - r1)), (tuple(c1 + r1))),fill=(228, 127, 66), outline=None)
draw.ellipse(((tuple(c2 - r1)), (tuple(c2 + r1))),fill=(228, 127, 66), outline=None)
for i in np.radians(range(0,360,60)):
    x2,y2 = np.cos(i)* 120,np.sin(i)* 120
    draw.ellipse((tuple(np.array([x2, y2]) + c1 - r2), 
                  tuple(np.array([x2, y2]) + c1 + r2)),fill=(146, 164, 184), outline=None)
for i in np.radians(range(0,360,45)):
    x2,y2 = np.cos(i)* 60,np.sin(i)* 60
    draw.ellipse((tuple(np.array([x2, y2]) + c2 - r3), 
                  tuple(np.array([x2, y2]) + c2 + r3)),fill=(146, 164, 184), outline=None)
plt.tick_params(labelbottom=False,labelleft=False,labelright=False,labeltop=False)
plt.tick_params(bottom=False,left=False,right=False,top=False)
plt.imshow(np.array(im))
plt.show()
3

右のオレンジ円の方が
左のオレンジ円よりも
大きく見えませんか?


ヘリング錯視


中央から放射状に線を描き
それをまたがるように横線を描くと
横線が中央から出る線をまたぐ部分が
膨らんで見えるという錯視です。

plt.figure(figsize=(20,9))
size = (800, 400)
im = Image.new("RGB", size, color=(255, 255, 255))

draw = ImageDraw.Draw(im)
num = 24
times = size[0]//num
color = (150, 100, 220)
for i in range(num):
    draw.line([(i*times,0),(size[0]-i*times,size[1])] , width = 2, fill = (100,100,100))
draw.line([(0,size[1]//3 ),(size[0],size[1]//3 )] , width = 5, fill = color)
draw.line([(0,size[1]//3*2),(size[0],size[1]//3*2)] , width = 5, fill = color)

plt.tick_params(labelbottom=False,labelleft=False,labelright=False,labeltop=False)
plt.tick_params(bottom=False,left=False,right=False,top=False)
plt.imshow(np.array(im))
plt.show()
4

中央の横線部分が
膨らんで見えませんかね?



デルブーフ錯視
円の過小視、過大視


青い円の大きさは同じですが
その中や外に円を描くと
元の円の大きさが小さく見えたり
大きく見えたりします。

plt.figure(figsize=(20,9),dpi=300)
size = (640, 320)
im = Image.new("RGB", size, color=(255, 255, 255))

draw = ImageDraw.Draw(im)
color = (0, 200, 220)
draw.arc((150 , 100 , 250 , 200), start=0, end=360, fill=color)
draw.arc((160 , 110 , 240 , 190), start=0, end=360, fill=(0, 0, 0))
draw.arc((350 , 100 , 450 , 200), start=0, end=360, fill=color)
draw.arc((340 , 90   , 460 , 210), start=0, end=360, fill=(0, 0, 0))

plt.tick_params(labelbottom=False,labelleft=False,labelright=False,labeltop=False)
plt.tick_params(bottom=False,left=False,right=False,top=False)
plt.imshow(np.array(im))
plt.show()

5

青い円の大きさは一緒ですが
違和感を覚えませんか?


このような錯視は
まだまだ他にもたくさんあります。

今回は一旦PILライブラリで画像を作成して
それをmatplotlibで描画するという方法をとりました。

こうすると簡単に線を引いたりして
錯視画像を作成できます。

みなさまも錯視ができると
とっても錯xyじゃないですかー!!!

って言いたいだけのネタでした。

BIツールの最高峰
Tableauがver10.2になって
Pythonが使えるようになりました

使い方

1.
Tableau10.2をインストールするかアップグレード 

2.
TabPyをダウンロード

git clone git://github.com/tableau/TabPy

gitコマンドでのダウンロードになるので
gitが無い人は要git install 

3.
TabPyディレクトリに移動

cd TabPy

4. 
TabPyサーバーのインストール

sh setup.sh (Macの場合)
setup.bat (Windowsの場合)

※ここでエラーが出るかも知れませんが
普通に使えました

5.
TabPyサーバーを起動

anacondaを既にインストールしている場合
anacondaディレクトリ配下に
インストールされるみたいなので
そこの中のstartup.sh(windowsはstartup.bat)を使って起動させる

起動させるとポート9004で立ち上がる

6.
Tableau側の連携設定

外部サービス接続設定で
no title

サーバー:localhost
ポート:9004
を指定する

※外部サーバーを指定することも可能

これで環境は整ったのであとは使う側


TableauからPythonの呼び出し方

計算式を作り
SCRIPT_REAL関数等を使って呼び出す

構文
SCRIPT_REAL(
'Pythonスクリプト' , 引数指定するメジャー1 , 引数指定するメジャー2 ・・・)

引数は2個以上設定可能なため , で繋げて行く

Pythonスクリプトの部分は
Pythonの関数を定義するような形にする

引数をPython側に渡すには引数名を
_arg1 , _arg2 ・・・のような命名にする

例:
サンプルストアのデータを使って
numpyで売上、利益の相関係数を返す

1

SCRIPT_REAL( '
import numpy as np
return np.corrcoef(_arg1,_arg2)[0,1]
' , 
SUM([売上]) ,
SUM([利益]) )

2つの引数がPython側に渡り
計算値がreturnでTableau側に返ってきます

この場合単に計算式を作って配置しただけだと
式のエラー表示が出ます

これは表計算で
ディメンジョンを使用しているからです

なので式の表計算設定で
使っているディメンジョンを指定してやります
(この場合は顧客名)
フィルターに設定する場合も同様です

最後に
トヨタの株価の推移と
米ドルの価格をつかって
どれだけ相関しているかを求めてみました

toyota

期間でフィルターしており
2016年10月から現在までのトヨタの株価と
米ドルの相関性は93%ほどになりました

期間によっては相関していない部分もあったり
こういう調査をするのにプログラムコードを書かずに
マウス操作だけで出来るようになるのは
Tableauの強みかと思います

因みに
Python連携できるのは
Tableau Desktopか
Tableau Serverだけで
Public版ではできないようです

買うしか無いとかwww



 

このページのトップヘ