個人的神殿

プログラミング

NumPy 要素の参照

リストと同じようにスライスできる。

x = np.arange(10)
x
x[3]

x[1:4]

x[4:-1:2]
[0 1 2 3 4 5 6 7 8 9]

3

[1 2 3]

[4 6 8]


多次元配列も多次元リストと同様

x = np.random.randint(1, 10, size=(4, 5))

x

x[3]

x[3][0]
[[4 6 5 7 6]
 [4 5 8 2 5]
 [9 3 8 5 7]
 [8 2 9 8 1]]

[8 2 9 8 1]

8


配列はリストと異なり、,で区切って要素を参照できる。

x = np.random.randint(1, 10, size=(4, 5))

x

x[0][1]
x[0, 1] # 0行1列目

x[:, 1]  # 1列目

x[0, :]  # 0行目

x[0:3, 1:4] # 0~2行目まで取り出し、そのあと1~3列目まで

x[::2,::2] # 各次元を1つ飛ばして参照
[[4 5 1 4 7]
 [4 5 6 7 4]
 [9 3 3 1 7]
 [6 8 5 5 2]]

5
5

[5 5 3 8]
[4 5 1 4 7]

[[5 1 4]
 [5 6 7]
 [3 3 1]]

[[4 1 7]
 [9 3 7]]

スライスで取得したものはビューと呼ばれ、、元の配列と同じメモリ上のデータを参照している。気をつけなければいけないのは、ビューの要素を変更した場合、同じメモリ上のデータを参照している配列も変更されることになる。

x = np.random.randint(1, 10, size=(4, 5))

x

y = x[:3, :3]

y

y[:, :] = 0 # yの要素を全て0にする

y

x
[[7 2 8 6 2]
 [4 3 6 2 7]
 [9 5 2 4 5]
 [5 4 7 7 9]]

[[7 2 8]
 [4 3 6]
 [9 5 2]]

[[0 0 0]
 [0 0 0]
 [0 0 0]]

# ↓!?
[[0 0 0 6 2]
 [0 0 0 2 7]
 [0 0 0 4 5]
 [5 4 7 7 9]]


これを解決するにはcopyメソッドを使用。
この返り値は部分配列のデータは新しくメモリ上にコピーされる。

z = x[:3, :3].copy()

z

z[:, :] = -5

z

x
[[7 2 8]
 [4 3 6]
 [9 5 2]]

[[-5 -5 -5]
 [-5 -5 -5]
 [-5 -5 -5]]

# ↓影響無し
[[0 0 0 6 2]
 [0 0 0 2 7]
 [0 0 0 4 5]
 [5 4 7 7 9]]


ファンシーインデックス参照という、整数要素のリストや配列を
インデックスに使う参照方法がある。
これははじめからコピーとして切り出すのでもとの配列に影響は無い。

x = np.random.randint(1, 10, size=(4, 4))

x

# xの0番目と3行目の行から成る配列は
x[[0, 3]]

# 0行2列めと2行3列目の要素から成る配列は
x[[0, 2], [2, 3]]
[[6 9 8 5]
 [2 9 5 5]
 [6 4 2 2]
 [5 2 3 1]]

[[6 9 8 5]
 [5 2 3 1]]

[8 2]

    
    
  

NumPy 色々な配列を作る②

続き

diagメソッドでは一次元のリストを引数に取り、その要素を対角成分とする対角行列を作成できる。
eyeと同様に対角成分を並べる位置を指定できる。

np.diag([1, 2, 3])

np.diag(np.linspace(1, 10, 3), k=1)
[[1 0 0]
 [0 2 0]
 [0 0 3]]

[[ 0.   1.   0.   0. ]
 [ 0.   0.   5.5  0. ]
 [ 0.   0.   0.  10. ]
 [ 0.   0.   0.   0. ]]

diagflatメソットでは二次元のリストからも対角行列を作れる。

np.diagflat([[1, 2], [3, 4]])

np.diagflat([[1, 2], [3, 4]], k=1)
[[1 0 0 0]
 [0 2 0 0]
 [0 0 3 0]
 [0 0 0 4]]

[[0 1 0 0 0]
 [0 0 2 0 0]
 [0 0 0 3 0]
 [0 0 0 0 4]
 [0 0 0 0 0]]

triメソッドで要素の値が1の下三角行列を作れる。
これも対角成分の位置を指定可能。

np.tri(3)

np.tri(2, 3, k=1)
[[1. 0. 0.]
 [1. 1. 0.]
 [1. 1. 1.]]

[[1. 1. 0.]
 [1. 1. 1.]]

既存の配列から下三角行列を作るには、trilメソッドを使用。
これも対角成分の位置を指定可能。

x = np.array([[1, 2], [3, 4]])

np.tril(x)

np.tril(x, k=-1)
[[1 0]
 [3 4]]

[[0 0]
 [3 0]]

上三角行列を作るにはtriuメソッドを使う。

x = np.array([[1, 2], [3, 4]])

np.triu(x)

np.triu(x, 1)
[[1 2]
 [0 4]]

[[0 2]
 [0 0]]

2変数関数をグラフ化するとき、二次元座標の配列を作りたい場合はmeshgridメソッドを使用する。

# x方向のベクトル
x = np.array([0, 1, 2])

# y方向のベクトル
y = np.array([0, 2, 4])

# meshgridメソッドはこれらのベクトルを引数に取り、二次元座標の行列を作成する。
x, y = np.meshgrid(x, y)
print(x)
print(y)

# z = x^2 + yの格子状の行列
print(x**2 + y)
[[0 1 2]
 [0 1 2]
 [0 1 2]]

[[0 0 0]
 [2 2 2]
 [4 4 4]]

[[0 1 4]
 [2 3 6]
 [4 5 8]]

tileメソッドで、指定した配列を指定回数並べた行列を作れる。
第1引数に元になる配列、第2引数には繰り返し回数を指定。

x = np.array([[1, 2], [3, 4]])

np.tile(x, 2)

np.tile(x, (2, 3))
[[1 2 1 2]
 [3 4 3 4]]

[[1 2 1 2 1 2]
 [3 4 3 4 3 4]
 [1 2 1 2 1 2]
 [3 4 3 4 3 4]]

配列を要素ごとに繰り返す配列を作るにはrepeatメソッドを使う。

x = np.array([[1, 2], [3, 4]])

# デフォルトでは各要素を指定回数繰り返した1次元配列が作られる。
np.repeat(x, 3)

# キーワード引数のaxisにより、何番目の軸方向に各要素を繰り返すかを指定する。
np.repeat(x, 2, axis=0)

# 繰り返し回数をリストにすることで行と列に対しての繰り返し回数も指定可能。
np.repeat(x, [2, 3], axis=1)
[1 1 1 2 2 2 3 3 3 4 4 4]

[[1 2]
 [1 2]
 [3 4]
 [3 4]]

[[1 1 2 2 2]
 [3 3 4 4 4]]

NumPy 色々な配列を作る①

NumPyを使った色々な配列の作り方まとめ①

リストからNumPyの配列を作る。
型はndarrayという名前だそうだ。

これは一次元配列。
次元はndim属性、各軸方向の大きさはshape属性で得られる。

import numpy as np

# 一次元配列
x = np.array([1, 2, 3, 4])
x
x.ndim
x.shape
[1 2 3 4]

1

(4,)

これは二次元配列、いわゆる行列。

x = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
x
x.ndim
# 2行4列の行列
x.shape
[[1 2 3 4]
 [5 6 7 8]]

2

(2, 4)

要素の方は統一されるようになっていて、dtypeで型を指定できる。

# 整数型
np.array([1, 2, 3, 4], dtype=np.int)
# 浮動小数点型
np.array([1, 2, 3, 4], dtype=np.float)
# 複素数型
np.array([1, 2, 3, 4], dtype=np.complex)
[1 2 3 4]

[1. 2. 3. 4.]

[1.+0.j 2.+0.j 3.+0.j 4.+0.j]

要素が全て0の配列はzerosメソッドで作成
要素が全て1の配列はonesメソッドで作成

# 要素が全て0の配列はzeros関数で作成

np.zeros(2)

np.zeros((3, 2))

np.ones((2, 3))
[0. 0.]

[[0. 0.]
 [0. 0.]
 [0. 0.]]

[[1. 1. 1.]
 [1. 1. 1.]]

任意の形状の配列を作成したいときにはempty。
要素の値が初期化されていないので作成にかかる時間が短い。
fillメソッドで、配列の全要素を指定の値に変更できる。

またfullメソッドでは、上の2つを合わせた、要素が一定で任意の形状の配列を作れる。

x = np.empty((2, 3))
print(x)

x.fill(1.5)
print(x)

x = np.full((2, 3), 1.5)
print(x)
[[6.23042070e-307 3.56043053e-307 1.37961641e-306]
 [1.37962320e-306 1.78019354e-306 7.56602523e-307]]

[[1.5 1.5 1.5]
 [1.5 1.5 1.5]]

[[1.5 1.5 1.5]
 [1.5 1.5 1.5]]

ある配列と同じ形状で配列を作りたければ、
ones_like, zeros_like, full_like, empty_likeメソッドを使う。

x = np.empty((2, 3))

np.ones_like(x)

np.zeros_like(x)

np.full_like(x, 1)

np.empty_like(x)
[[1. 1. 1.]
 [1. 1. 1.]]

[[0. 0. 0.]
 [0. 0. 0.]]

[[1. 1. 1.]
 [1. 1. 1.]]

[[1. 1. 1.]
 [1. 1. 1.]]

arrangeメソッドで、一定間隔で要素の値が変化する配列を作れる。

np.arange(4)

np.arange(1, 6)

np.arange(1, 6, 0.8)
[0 1 2 3]

[1 2 3 4 5]

[1.  1.8 2.6 3.4 4.2 5.  5.8]

同じようなことをlinspaceメソッドでもできる。

# 0から1まで5等分する。
np.linspace(0, 1, 5)

# endpointをFalseにすると終了値が含まれない。
np.linspace(0, 1, 5, endpoint=False)

# 対数等間隔な値の要素を持つ配列はlogspaceメソッドを使う。
# 対数の底はデフォルトでは10。
# ↓は、logx = 0 から logx = 2までのxを10等分して返している。
np.logspace(0, 2, 10)

# 対数の底を変更するにはbaseの値を変更する。
# endpointも指定できる。
np.logspace(0, 2, 10, base=np.e, endpoint=False)
[0.   0.25 0.5  0.75 1.  ]

[0.  0.2 0.4 0.6 0.8]

[  1.           1.66810054   2.7825594    4.64158883   7.74263683
  12.91549665  21.5443469   35.93813664  59.94842503 100.        ]

[1.         1.22140276 1.4918247  1.8221188  2.22554093 2.71828183
 3.32011692 4.05519997 4.95303242 6.04964746]

単位行列はeyeメソッドで作る。
キーワード引数kで対角成分を並べる位置を指定できる。
また引数に行数と列数、kを与えると任意の形状の単位行列を作れる。

np.eye(3)

# 右に1列ズレたところからスタート
np.eye(3, k=1)
# 左に1列ズレたところからスタート
np.eye(3, k=-1)

# 2,3行列の1列目からスタート
np.eye(2, 3, k=1)
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]

[[0. 1. 0.]
 [0. 0. 1.]
 [0. 0. 0.]]

[[0. 0. 0.]
 [1. 0. 0.]
 [0. 1. 0.]]

[[0. 1. 0.]
 [0. 0. 1.]]

岩崎 武雄『西洋哲学史』 第1章のまとめ

 学校の図書館でたまたま手にとったこの本が面白かったので、第1章(創始期の哲学)を自分用にまとめた。デモクリトスという人が紀元前でもう既に原子の存在に気づいていたということは知っていてそれはすごいと思っていたのだが、それまでにどのような流れがあったのかは知らなかったからかなり新鮮だった。


第1章 創始期の哲学

1.ミレトス学派

 それまでは神話的に世界を説明しようという傾向が強かったが、そういった態度は捨て、世界を世界そのものから説明しようという動きが始まった。世界のアルケー(根源、原理、原質)というものがあり、それは世界のあらゆる現象の生成変化の中にあってかつ変化しない何かが存在するとして、それが一体何なのかを考えた。
 かの有名なタレスは、それは水であると言い、アナクシマンドロスは無限なるものと言った。有限なものからあらゆるものが生まれることは無いという理由らしい。そしてアナクシメネスは空気であると言った。それこそが無限なるものであると考えたのだろう。

2.エレア学派 vs ヘラクレイトス

 しかしアルケーが存在するとは言っても、それがなぜ存在し、なぜ生成変化するのかということについては触れられてはいなかった。このなぜに注目し、また存在と変化の両立は不可能であるという意見から、2つの立場に分かれることになる。

(a) 存在を重視して生成を否定し、アルケーの、一切のものの根源であるという性質にのみ注目。
(b) 生成を重視して存在を否定し、アルケーの、生成変化するという性質にのみ注目。

(a) エレア学派

(1) クセノパネス
 彼は詩人であり、また宗教家でもあった。多神教を否定し、アルケーというのは一にして一切であり、不動不滅の神であると考えた。

(2)パルメニデス
 クセノパネスの神の概念をさらに抽象化し、「有るもの」こそが真実であると考えた。この「有るもの」には以下の特徴がある。

 ①「有るもの」は不生不滅
 ②「有るもの」は不可分
 ③「有るもの」は不変不動

(3)ゼノン
 これまでの「有るもの」の思想を受け継ぎ、自分の思想とは反対の、雑多と運動をいったん認める立場に立ち、矛盾を導くという論法を取った。(アリストテレスは彼を弁証法創始者であると言った。)

(4)メリッソス
 彼もパルメニデスの「有るもの」の思想を受け継ぎ、更に「有るもの」は空間的にも無限であると考えた。

(b) ヘラクレイトス

 一切はただ生成変化するのみであると考えた。(有名な、万物は流転するという言葉はこのことであった。)そしてアルケーとは火だと言ったが、常に生成変化し続けるものの代表的な意味合いがあったそうだ。ただ唯一不変なものがあり、それは生成変化の法則「ロゴス」であると考えた。これがあるおかげで、世界は常に変化し続けているにも関わらず秩序を維持できていると考えた。

3.ピタゴラス学派と多元論者

 当然だが、それまで対立していた存在と生成変化、この2つを共に認めようと動きが出てくる。

(a) ピタゴラス学派

 アルケーは数であると考えた。この変化的な事物の世界は、数の世界をまねて作られたという。数というのは、「有るもの」と同じく永遠不動の存在であり、かつ変化家的な事物である、というのも、この世界の事物が変化するのに対してその中にある数的な関係は決して変化しないかららしい。(数学や音楽、天文学などの研究から)

(b) 多元論者

 存在と生成変化が両立するとはいっても、なぜ両者が矛盾無く存在できるのかを考えた。多数の「有るもの」が存在し、それらの運動によってあらゆるものが生成される、つまりアルケーは多数存在していると考えた、という意味で彼らは多元論者と言われている。

(1) エンペドクレス
 アルケーは、火、水、空気、地であると考えた。この4つは不生不滅だが、互いに性質が異なっておりまた分割は不可能である。
 どのようにして生成が生じるかというと、この4つの元素が様々な割合で混合することで様々な性質を持った現実の事物が生成し、また混合されたものが分離することで消滅する。では何によって混合が起こるかというと、それは「愛」と「憎」という何か神秘的な力を持つものであると考えた。

(2) アナクサゴラス
 エンペドクレスの話を拡張し、アルケーはこの4つの元素に限らず、現実に存在する無数の事物が持つ無数の性質の数だけ無数のアルケーがあると考え、それを種子(スペルマタ)と呼んだ。4つの元素だけでは、無数の性質を説明できないと考えたらしい。
 では何によって混合が起こるというと、それは精神(ヌース)であると言った。ただこれは混合の一番最初に作用するのみで、一度運動が始まれば種子たちの混合や分離は機械的に行われるのだという。

(3) デモクリトス
 アナクサゴラスの話と似ているが、種子は性質的差別を有するものとは見ず、それらは量的な差別、すなわち形態や大きさなどが違っている、そしてそれをアトム(原子、不可分なもの)と呼んだ。
 パルメニデスの「有るもの」と同じく不生不滅だが、運動は認め、その運動によって生成変化を説明しようとしたが、運動が可能なためには動くための空虚な空間が必要となる。パルメニデスはそれを「有らぬもの」としてその存在は否定したが、デモクリトスは「有らぬもの」は有る、という風に考えた。つまりパルメニデスの「有るもの」を無数に多くのものに分割して、それらを空虚な空間の中で運動させたということだ。この運動によって原子たちが相互に衝突し合って混合や分離が行われる、その過程こそが生成である。色や味などの感覚的な性質も、ただアトムの運動によって現れているだけであるとも考え、つまりそれまでのいわゆる質的差別を量的差別に還元している。
 ではなぜそのような運動が起こるのかという話になるが、今までは何か別の力が働いて運動していると言うのが一般的だったが、デモクリトスは、他に原因は無くただアトムというのは運動する性質を持っているから運動しているだけのことだと言った。

 ここに機械論的な世界観が打ち立てられることとなる。

 

matplotlibで簡単なグラフを描く

はじめに  y = 2x - 6のグラフを描く。

import matplotlib.pyplot as plt

# 2x - 6 

x = [i for i in range(-5, 5)]
y = [2 * i - 6 for i in x]

plt.plot(x, y) # グラフのプロット

plt.title("linear function") # グラフの名前

plt.xlabel("x") # x軸の名前
plt.ylabel("y") # y軸の名前

plt.grid() # グラフにグリッドを追加

plt.show() # グラフの表示

x軸、y軸の値をそれぞれリストにして、plot(x, y)でグラフを描いている。

f:id:beyonce_t:20191111225507j:plain


次はy=2x^2 + 3x - 1のグラフを描く。

# 2x^2 + 3x - 1

x = [i for i in range(-5, 5)]
y = [2 * i ** 2 + 3 * i - 1 for i in x]

plt.plot(x, y)

plt.title("quadratic function")

plt.xlabel("x")
plt.ylabel("y")

plt.show()

f:id:beyonce_t:20191111225529j:plain


カクついてしまっている。
これはxの値が0, 1, 2,…のように不連続な値を取っており尚且つその数が少なすぎるからというのが理由か。
いくら不連続でも数を増やしてやれば見た感じは滑らかに見えるので、その数を増やしてみる。

x = [i for i in range(-50, 50)]
  • 5 ~ 4までの整数だったのを -50 ~ 49 までの整数にした。これで大分滑らかになった。

f:id:beyonce_t:20191111230047j:plain

ロマンシング サガ リ・ユニバースの七英雄戦を耳コピした

リ・ユニバースというロマサガのソシャゲを一時期やっていたが周回する時間が取れないのでやめた。

でも七英雄の第二形態のBGMが最高に良いのでまたdominoで作ってみた。

相変わらず、出来上がったあと改めて原曲を比較すると大分違うなぁという印象。

まぁdominoだからってこともあるんだろうけど何だかんだ自分が気持ちよければそれで良いと思っているからね。耳コピというか完全に自分用アレンジって感じだな(笑)

黒の預言書の動画はdominoで再生している様子をbandicamで撮ってそのままアップロードしたんだけど、音と動画は別々でとってあとで合体させるのが普通みたい、ってかよくよく考えたら当たり前ですね……。

というわけで俺も今回は録音をAudacityで、動画はbandicam、んでAudacityで少しリバーブとかイコライザを使ってみたりしたあと、Windowsに付属で付いている動画編集ソフトで完成させた。

www.youtube.com

BeautifulSoupでスクレイピング 基本のまとめ

まぁこれもネット上にはたくさん情報があるが、やはり自分で何かをやらないと頭に入らないような気がするのでここにまとめておこうと思う。

今回は以下のサイトを対象に試してみる。
wiki3.jp

まずはhtmlを取得したいのだが、pythonに標準で付いているurllib.requestだとエラーが出てしまうので、requestsモジュールを使うことにする。
www.yoheim.net

import requests

url = "https://wiki3.jp/occult_"
html = requests.get(url)
print(html.text)

こんな感じでhtmlを文字列として取得できる。

<!DOCTYPE html>
<html lang="ja" prefix="og: http://ogp.me/ns#">
<head>

<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60774119-9"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'UA-60774119-9');
  gtag('config', '');
</script>
<meta charset="utf-8">
……

次はBeautifulSoupを使っていく。

まず、bs4をインストールする。

pip install bs4

そしてこのように書く。

import requests
from bs4 import BeautifulSoup

url = "https://wiki3.jp/occult_"
html = requests.get(url)

bs_obj = BeautifulSoup(html.text, "html.parser")
print(bs_obj.find("h1"))

するとこのようになる。

<h1><a class="uk-link-muted" href="/occult_">Hiroのオカルト図書館</a></h1>

BeautifulSoupの第1引数に解析対象のHTMLを渡し、第2引数でどのパーサーを使用するか決める。
"html.parser"はpythonの標準ライブラリのparserなのだが、
vaaaaaanquish.hatenablog.com

↑のサイトを参考にしたら、もっと良いパーサーを使ったほうが良いらしい。
なので

pip install lxml
bs_obj = BeautifulSoup(html.text, "lxml")

もしくは

pip install html5lib
bs_obj = BeautifulSoup(html.text, "html5lib")

と書くことにする。

次はhtmlから必要な情報を取る作業を行いたい。

①.find()
何か特定のHTMLタグの、「最初の」1つだけ抽出することができる。
例えば最初のh1タグを取り出したいというときは、

print(bs_obj.find("h1"))
<h1><a class="uk-link-muted" href="/occult_">Hiroのオカルト図書館</a></h1>

タグを抜いて、「Hiroのオカルト図書館」という文字列だけを抜きたいときは、textにアクセスする。

print(bs_obj.find("h1").text)
Hiroのオカルト図書館

属性値にアクセスしたい場合は、get()を使い、属性の名前を指定する。
例えば上のh1タグの中のaタグの中のclass属性を得たい場合は、

print(bs_obj.find("h1").find("a").get("class"))

こんな感じでリストになって返ってくる。

['uk-link-muted']


②find_all()
find()と違い、条件に合致するタグをリストとして全て返す。

print(bs_obj.find_all("h1"))
[<h1><a class="uk-link-muted" href="/occult_">Hiroのオカルト図書館</a></h1>, <h1>メニュー</h1>, <h1 class="uk-text-muted uk-h3"><span class="tc_whitesmoke"><span class="tc_snow">最近更新したページ</span></span></h1>, <h1><span class="tc_gainsboro">カウンター</span></h1>,
<h1>トップページ</h1>]

これをfor文で回して文字列を抽出してみると

[print(bs_obj.string) for bs_obj in bs_obj.find_all("h1")]
Hiroのオカルト図書館
メニュー
最近更新したページ
カウンター
トップページ


全てのリンク先を得たい場合は、aタグの中のhref属性を調べれば良いのでこうする。

[print(link.get("href")) for link in bs_obj.find_all("a")]
/
/signUp
/guide

/occult_/edit?mode=1

/occult_/edit/1
/occult_/edit/2
...


h1タグとh2タグといったように複数のタグを同時に抽出したい場合は{}でくくる。

print(bs_obj.find_all({"h1", "h2"}))

さらにh1タグとh2タグの中の、class属性が"uk-text-muted"のものを抽出したい場合は

print(bs_obj.find_all({"h1", "h2"}, {"class": "uk-text-muted"}))
[<h2 class="uk-text-muted uk-h3"><span class="tc_black">グリモア魔術</span></h2>, <h2 class="uk-text-muted uk-h3"><span class="tc_black">古代魔術</span> </h2>, <h2 class="uk-text-muted uk-h3"><span class="tc_black">ルネッサンス魔術</span></h2>, <h2 class="uk-text-muted uk-h3"><span class="tc_black">現代魔術</span></h2>, <h2 class="uk-text-muted uk-h3"><span class="tc_black">魔女術</span></h2>, <h2 class="uk-text-muted uk-h3"><span class="tc_black">錬金術</span></h2>, <h2 class="uk-text-muted uk-h3"><span class="tc_black">秘密結社</span></h2>, <h2 class="uk-text-muted uk-h3"><span class="tc_black">カバラ</span></h2>, <h1 class="uk-text-muted uk-h3"><span class="tc_whitesmoke"><span class="tc_snow">最近更新したページ</span></span></h1>]