Cucco’s Compute Hack

コンピュータ関係の記事を書いていきます。

pythonで逐次入力に対して移動平均を計算するためのクラス

pythonで、逐次入力に対して移動平均を計算する。
移動平均幅は、コンストラクタの引数に与えておく。

以下、ソース。

# -*- coding: utf-8 -*-

class MovingAverage:
	"""逐次入力に対して移動平均を計算するためのクラス"""

	def __init__(self,size):                  # コンストラクタ
		self.pc = 0
		self.data=[0]*size	#リングバッファとして使う
		self.size=size
		self.full=False

	def put(self,value):
		self.data[self.pc]=value
		self.pc=self.pc+1
		if self.pc==self.size:
			self.pc = 0
			self.full=True
		return self.full

	def print(self):
		#デバッグ向けリングバッファの中身確認用
		print(self.data)

	def average(self):
		if self.full:
			return sum(self.data)/self.size
		else:
			#入力が足りないときにも一応値を返してみる。
			return sum(self.data)/self.pc

def main():
	mv2=MovingAverage(3)
	
	mv2.put(4)
	mv2.print()
	print(mv2.average())
	mv2.put(5)
	mv2.print()
	print(mv2.average())
	mv2.put(6)
	mv2.print()
	print(mv2.average())
	mv2.put(7)
	mv2.print()
	print(mv2.average())

if __name__== '__main__':
    main()

実行結果

C:\Python34>C:\Python34\python.exe C:\Python34\movingaverageclass.py
[4, 0, 0]
4.0
[4, 5, 0]
4.5
[4, 5, 6]
5.0
[7, 5, 6]
6.0

Matlab 2016bのwebreadがおかしい

Matlab 2016bのwebreadの動きがおかしかったのでメモ。

問題

Matlab 2016aでは正しく動いていたのに、Matlab 2016bにあげたらbad requestが返ってくるようになった。

原因?

URLの中にある時刻の表現の中で%3Aのエンコードがおかしなことになってることが判明。
URLの中に%3Aを含めると%253Aになったり、:(コロン)で表現するとコロンのままで、%3Aにならなかったり。

暫定対策

C:\Program Files\MATLAB\R2016b\toolbox\matlab\external\interfaces\...
webservices\http\+matlab\+net\QueryParameter.m(429,9)
noEncodeCharsの'/?'を'/?%'に変更して、%を%のままエンコードしないように指定すると、とりあえず動いた。

メモ

アクセス権がないので、Administrator権限で、編集権限を与えてから編集しましょう。

PythonからMatlabの関数を呼び出す

matlab.engineのインストール

管理者権限で起動したコマンドプロンプトで以下を実行

cd "C:\Program Files\MATLAB\R2016a\extern\engines\python\"
C:\Python34\python.exe "C:\Program Files\MATLAB\R2016a\extern\engines\python\setup.py" install

なぜか「ImportError: No module named 'matlab'」

実行するとこんなエラーに。
ImportError: No module named 'matlab'

matlab.engineは以下にあります。
C:\Python34\Lib\site-packages\matlab\engine

解決策1 環境変数でPYTHONPATHを指定して実行する

C:\Program Files\MATLAB\R2016a\extern\engines\python>SET PYTHONPATH="C:\Python34\Lib\site-packages"

C:\Program Files\MATLAB\R2016a\extern\engines\python>"C:\Python34\python.exe" "C:\Users\Cucco\Documents\MATLAB\matengen.py"
[[1.0,2.0,3.0,4.0,5.0]]

解決策2 実行する.pyファイルの中でパスを記載する

# -*- coding: utf-8
import sys
sys.path.append('C:\Python34\Lib\site-packages')
import matlab.engine

eng = matlab.engine.start_matlab()
a = matlab.double([1,4,9,16,25])
b = eng.sqrt(a)
print(b)

実行結果

C:\Python34>C:\Users\Cucco\Documents\MATLAB\matengen.py
[[1.0,2.0,3.0,4.0,5.0]]
参考文献

yak-shaver.blogspot.jp

Matlabで1×Nのサイズのベクトルを2次元配列に変換

まずは変換のルールを確認

3×4の2次元配列を用意。

>> a=[[1 2 3 4]; [5 6 7 8]; [9 10 11 12]]

a =

     1     2     3     4
     5     6     7     8
     9    10    11    12

reshape()で1×Nに変換。列方向に拾って1×Nを作る様子。

>> b=reshape(a,1,[])

b =

     1     5     9     2     6    10     3     7    11     4     8    12

4列の形にしてほしいので、reshape()でn×4に変換。元に戻りました。

>> c=reshape(b,[],4)

c =

     1     2     3     4
     5     6     7     8
     9    10    11    12

元に戻りました。

行方向で2次元配列を拾って行ってほしい

手元にあるデータの並びは行方向に拾った感じのデータなので、それを2次元配列にしたい。

1×nのベクトルを用意。

>> d=[1 2 3 4 5 6 7 8 9 10 11 12]

d =

     1     2     3     4     5     6     7     8     9    10    11    12

あとで転置するので、行を4行になるようにreshape()

>> e=reshape(d,4,[])

e =

     1     5     9
     2     6    10
     3     7    11
     4     8    12

転置すると期待通りに。

>> f=transpose(e)

f =

     1     2     3     4
     5     6     7     8
     9    10    11    12

PythonからMySQLを操作する

構築

Python3.4とMySQL5.7を利用。

Pythonを先に入れておく。Python のバージョンは、Connectorの対応バージョンと合わせておく。

MySQLのインストール時には、rootユーザのパスワードの設定が必要。ここでは、passwordとします。

Connector

http://dev.mysql.com/downloads/connector/python/

Connector自体は、MySQLインストーラに含まれている様子。

準備

データベースを作ります。

スタートメニューにいる”MySQL 5.7 Command Line Client - Unicode”を開いて、ログイン。

最初はこんな感じのデータベースがある。show databases;がコマンド。

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sakila             |
| sys                |
| world              |
+--------------------+
6 rows in set (0.00 sec)

データベースを作ります。create database testdb;がコマンド。testdbがデータベース名。

mysql> create database testdb;
Query OK, 1 row affected (0.01 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sakila             |
| sys                |
| testdb             |
| world              |
+--------------------+
7 rows in set (0.00 sec)

テストコード

pythonで以下を実行

# -*- coding: utf-8

import mysql.connector

config = {
    'user': 'root',
    'password': 'password',
    'host': 'localhost',
    'database':'testdb',
    'charset':'utf8'
}
cnx = mysql.connector.connect(**config)
cur = cnx.cursor(buffered=True)

sql = 'DROP TABLE IF EXISTS pet;'
cur.execute(sql)
cnx.commit()

sql = 'CREATE TABLE pet (name VARCHAR(20), owner VARCHAR(20),species VARCHAR(20), sex CHAR(1), birth DATE, death DATE);'
cur.execute(sql)
cnx.commit()

# select
cur.execute('SELECT * FROM pet;')
row = cur.fetchone()

sql = 'INSERT INTO pet VALUES (%s, %s, %s, %s, %s, %s);'
data= ('Puffball','Diane','hamster','f','1999-03-30',None)
cur.execute(sql, data)

sql = 'INSERT INTO pet VALUES (%s, %s, %s, %s, %s, %s);'
data= ('Puffball','Diane','hamster','m','1999-03-30',None)
cur.execute(sql, data)
cnx.commit()

# select
cur.execute('SELECT * FROM pet;')
row = cur.fetchall()

# 出力
for i in row:
	print(i)

cur.close()
cnx.close()

実行結果

C:\Python34>python C:\Python34\msql_test.py
('Puffball', 'Diane', 'hamster', 'f', datetime.date(1999, 3, 30), None)
('Puffball', 'Diane', 'hamster', 'm', datetime.date(1999, 3, 30), None)

MySQL 5.7 Command Line Clientでテーブル定義の情報を見てみると

mysql> describe pet;
+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| name    | varchar(20) | YES  |     | NULL    |       |
| owner   | varchar(20) | YES  |     | NULL    |       |
| species | varchar(20) | YES  |     | NULL    |       |
| sex     | char(1)     | YES  |     | NULL    |       |
| birth   | date        | YES  |     | NULL    |       |
| death   | date        | YES  |     | NULL    |       |
+---------+-------------+------+-----+---------+-------+
6 rows in set (0.00 sec)
mysql> select * from pet;
+----------+-------+---------+------+------------+-------+
| name     | owner | species | sex  | birth      | death |
+----------+-------+---------+------+------------+-------+
| Puffball | Diane | hamster | f    | 1999-03-30 | NULL  |
| Puffball | Diane | hamster | m    | 1999-03-30 | NULL  |
+----------+-------+---------+------+------------+-------+
2 rows in set (0.00 sec)

メモ

データベースを作っておかないと、Pythonから接続ができません。

NULL値を入れたい場合は、Noneを入れておけばよい様子。

cnx.commit()がないと、Insertが反映されません。

エラーコードと原因

パスワード間違い

mysql.connector.errors.ProgrammingError: 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

データベースが見つからない

mysql.connector.errors.ProgrammingError: 1049 (42000): Unknown database 'foo'

すでにテーブルがある

mysql.connector.errors.ProgrammingError: 1050 (42S01): Table 'pet' already exists

移動平均

移動平均を返す関数movingAverage。

function [ output_args ] = movingAverage(dataNx1,AverageWindowSize )
    filterfunc=ones(1,AverageWindowSize);
    output_args = filter(filterfunc,AverageWindowSize,dataNx1);
end

テストコード。yとして、sin関数の値にランダムノイズを加えておく。

x=0:0.05:2*pi;
y=sin(x)+rand(size(x))*0.1;
plot(x,y)
hold on
plot(x,movingAverage(y,5))

結果。青がy。赤が移動平均

f:id:Cucco:20160720230023j:plain

 

 

行列の重複排除

uniqueを使って、複数の行列から、同じ行列を削除する。

2×4の行列をいくつか作っておく。a4とa5が重複。

>> a1=[1 2 3 4; 5 6 7 8]
a2=[2 3 4 5; 6 7 8 9];
a3=[3 4 5 6; 7 8 9 0];
a4=[1 2 3 4; 5 6 7 8];
a5=[2 3 4 5; 6 7 8 9];

a1 =

     1     2     3     4
     5     6     7     8

 reshapeで行ベクトルにして、つなげておく。

>> a1v=reshape(a1,1,[ ])
a2v=reshape(a2,1,[ ]);
a3v=reshape(a3,1,[ ]);
a4v=reshape(a4,1,[ ]);
a5v=reshape(a5,1,[ ]);

aa=[a1v;a2v;a3v;a4v;a5v]

a1v =

     1     5     2     6     3     7     4     8


aa =

     1     5     2     6     3     7     4     8
     2     6     3     7     4     8     5     9
     3     7     4     8     5     9     6     0
     1     5     2     6     3     7     4     8
     2     6     3     7     4     8     5     9

行単位でuniqueを実行して、reshapeで2×4の行列に戻す。

>> ua=unique(aa,'rows')

size(ua)

reshape(ua(1,:),2,4)
reshape(ua(2,:),2,4)
reshape(ua(3,:),2,4)

ua =

     1     5     2     6     3     7     4     8
     2     6     3     7     4     8     5     9
     3     7     4     8     5     9     6     0


ans =

     3     8


ans =

     1     2     3     4
     5     6     7     8


ans =

     2     3     4     5
     6     7     8     9


ans =

     3     4     5     6
     7     8     9     0