Hatena::ブログ(Diary)

小酒井輝の断片3 このページをアンテナに追加 RSSフィード

August 02(Tue), 2011 Mac OS X (Lion) に python - scipy インストールする時の変更点 このエントリーを含むブックマーク

pip install scipy

としたところ、以下のエラーが出ました。

/usr/bin/cc -fno-strict-aliasing -O3 -w -pipe -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -Iscipy/sparse/linalg/eigen/arpack/ARPACK/SRC -I/Users/akiraak/project/MRI-MFI/env/lib/python2.7/site-packages/numpy/core/include -c scipy/sparse/linalg/eigen/arpack/ARPACK/FWRAPPERS/veclib_cabi_c.c -o build/temp.macosx-10.4-x86_64-2.7/scipy/sparse/linalg/eigen/arpack/ARPACK/FWRAPPERS/veclib_cabi_c.o
scipy/sparse/linalg/eigen/arpack/ARPACK/FWRAPPERS/veclib_cabi_c.c:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘float’
scipy/sparse/linalg/eigen/arpack/ARPACK/FWRAPPERS/veclib_cabi_c.c:10: error: expected ‘;’, ‘,’ or ‘)’ before ‘float’
scipy/sparse/linalg/eigen/arpack/ARPACK/FWRAPPERS/veclib_cabi_c.c:16: error: expected ‘;’, ‘,’ or ‘)’ before ‘*’ token
scipy/sparse/linalg/eigen/arpack/ARPACK/FWRAPPERS/veclib_cabi_c.c:21: error: expected ‘;’, ‘,’ or ‘)’ before ‘*’ token

そこでソースコードに #include <complex.h> を追加してあげます。

  • scipy/sparse/linalg/eigen/arpack/ARPACK/FWRAPPERS/veclib_cabi_c.c
  • scipy/lib/blas/fblaswrap_veclib_c.c.src
  • scipy/linalg/src/fblaswrap_veclib_c.c

と、書いたけど上手くいっていないようなので試行錯誤してみる。

July 29(Fri), 2011

sqlite3 - python DBファイルで:memory:を初期化する

sqlite3.connect(':memory:') でインメモリのDBを使う場合に中身を初期化しておきたい場合があります。一つの方法としてSQLを実行する方法があります。


conn = sqlite3.connect(':memory:', isolation_level=None)
c = conn.cursor()
sqls = [
    'CREATE TABLE table1 (data1 INTEGER, data2 INTEGER);',
    'INSERT INTO "table1" VALUES(1, 2);',
    'INSERT INTO "table1" VALUES(3, 4);'
]
for sql in sqls:
    c.execute(sql)

この方法でも良いのですが、データの量が多いと時間がかかります。たとえばカラム数4千でレコード数3万の場合2分ほど。これらの全てのカラムにインデックスを張った場合2時間ほどかかりました。


これでは時間がかかりすぎます。そこでSQLを実行するのではなく、事前に作成しておいたDBファイルをそのまま読み込んで初期化する方法を紹介します。


まずapswモジュールが必要になるので、こちらから落としてインストールしておきます。

そして、DBファイルで初期化を行う手順は以下のようになります。


import sqlite3
import apsw

_conn = apsw.Connection(':memory:') #1
conn = sqlite3.connect(_conn) #2
src_conn = apsw.Connection('src.db') #3

with _conn.backup("main", src_conn, "main") as backup:
    while not backup.done:
        backup.step(100) #4

  1. :memory: で apsw のコネクションを作成
  2. apsw で sqlite3 のコネクションを作成
  3. 初期化用のDBファイルで apsw のコネクションを作成
  4. 初期化用BDから :memory: へデータをコピーしていく

backup.step(100) で指定している数値は一度にコピーするページサイズです。小さくすればwhileが多く回りますが、適当な数値を入れておけば何を指定して問題ないと思います。


この方法を使うと、SQL文を実行したときにかかってた2時間が、なんと10秒まで短縮されました。


参考

sqlite3 - Python 中央値を得る集計関数を追加する

sqlite には ORACLE のように中央値を取得する集計関数 MEDIAN が無いようです。しかし以下のように自前の関数を追加することができます。


import sqlite3

class Median:
    def __init__(self):
        self.values = []

    def step(self, value):
        self.values.append(value)

    def finalize(self):
        srtd = sorted(self.values)
        alen = len(srtd)
        return 0.5*(srtd[(alen-1)//2] + srtd[alen//2])

conn = sqlite3.connect("sqlite.db")
conn.create_aggregate("median", 1, Median)
cur = conn.cursor()
cur.execute("select median(data1) from table1")

July 26(Tue), 2011 SQLAlchemy for Python から sqlite の connection を取得する このエントリーを含むブックマーク

import sqlalchemy
engine = sqlalchemy.create_engine('sqlite:///:memory:')
conn = engine.raw_connection().connection # sqlite3.connect(':memory:') で返るオブジェクトと同じ
Connection: close