体調管理(2)

アナログ放送が終わってしまった。これで、携帯のワンセグも、カーナビのTVも使い道が無くなっちゃった 訳だな。と、書くと、いかにも今まで利用してたっぽく聞こえるけど、おいらは両者共、一度も使った事 ないんだ。

携帯のワンセグは寝床で見るって使い方があるようだけど、電池がすぐに無くなるのが玉に傷と女房が 言ってた。そんなにTVっ子続けてどうする。どうせすぐに、TVも見られる携帯が売り出されるに違いない。 カーナビにTV付きって、どういうシチェーションを想定してたんですかね? てんこ盛りの機能で差を付けようって、メーカーの卑しい根性が発露したんですかね。

そう言えば、無線機でもTV対応機が有ったな。IC-7000 がそうだったように記憶してたんだけど、今見たらそんな機能は削除されてた。その代わり、RTTYで便利に 使えるような機能が乗ってた。こうやって、進化させてくんだな。

世は正にデジタル時代。CQ誌の付録と称して、EchoLinkだとか、D-STARだとかやっきになってる。今号の 付録はICOMさんの提供なんでしょうか。全部、ICOMの製品が推奨機器になってますよ。裏にはD-STARを 押してるJARLが居たりして面白いな。

新聞に目の不自由な方が今までTV放送の音声をラジオで聞いてたけど、デジタルに移行してからはだめに なったと載ってた。メーカーにお願いしても採算が合わないので断られたとかで途方に暮れてるって。採算に 合わないアマチュア機を数多く作ってきた無線機メーカーさん、一肌脱ぎませんかね。ICOMあたりが、 IC-7000D とかを企画して、その石をそっとラジオに乗せれば済む話なんですから。。。

家のTVに入ってる余計なカードが壊れた。B-CASとか言うやつですかね。TVの電源を入れると、カードを 挿入してくださいって画面に表示されるんだ。カードを引き出して接点を消毒してから入れても、カードを 認識しない。カードの中に入ってるROMが逝かれてしまったんですかね? 横浜にあるセンターから、新しい カードを送ってもらってやっと復旧した。全く、今のTVって余計な物が付いているんだから。

これもそれも、総務省の天下り先確保のための陰謀だな。アナログTVからデジタルTVに移行して、空いた 周波数帯を有効利用しますって、綺麗な事をぬかしているけど、本当の目的は利権の確保にあるんだな。 国民はいい迷惑ですよ。

統計

恐れ多くも、統計処理ソフトRを差し置いて、Pythonでもどきをやってる訳だけど、統計の考え方を ちょいと学んでおく。

暑いので、アイスクリーム統計学にようこそ!を 食しながらソフトに行こう。姉妹編に ハンバーガー統計学にようこそ! もあるけど、メタボになりそう(なってるって)なので、一応遠慮しとこう。 嗚呼、暑い時はアイスクリームよりも、ガリガリ君がいいのかな?

ソフトなやつばかりだと軟弱になっちまうので、ハードなやつも。IEしたら、今題材で取り上げている 血圧を話題にしたのが見つかった。 時系列解析ですって。 いきなりの専門用語ですよ。収縮期血圧 って、最高血圧でいいのかな? 多分そうだろう。 一応血圧で調べてみた。そして、日本高血圧学会 なんてのがある事を知った。これって、利権団体なんでしょうかね? いきなりメタボを言い出して、 利権を作ろうとしたものよりは実績がありそうだな。 高血圧は昔から市中に定着してるもんね。

でも、血圧って測る度に変わるんだよなあ。一瞬でも定義された範囲を超えると烙印を押されてしまうの だろうか? そこで、統計マジックですよ。時間的な変化を統計で捉えましょう。FFTしましょってのが 時系列解析なのね。一日の周期で血圧は変動する。更には、午前と午後でも変動する。そう言えば、定期健診時に 医者が、季節による変動もあるぜよって言ってたな。夏は低め、冬は高めになるって。

ざっとこの章を読んでみたけど、医者って統計屋さんなのね。あと、統計を操る人は、生命保険屋とか 金儲けしたい症候群の金融屋さん。世界を混乱に陥れて恥ずかしくないのかね。せいぜい、勝ち馬予想を する、お馬様Loveぐらいで止めておけばいいのにね。

統計はどうも数字をこねくり回して権威付けしてるみたいで、余り好きになれないのだけど、季節柄 放射線による発がん――データ解析屋的解説 こういうのには弱かったりします。

そして統計を真面目に勉強するなら、こういう事 を知ってると良いらしい。Rを使うと面白い 分析が出来るもんだな。そしてそれがR礼賛 に変わるのかな?

心臓について

そう言えば、定期健診の時に、心電図も取られたなあ。心電図って素人でも読めるんかな? 読めなくても、FFTとかしたら何とかなりそうな予感。昔スポーツクラブに入会した時、身体特性の把握とか 言われて、自転車漕ぎの試験をやらされましたよ。

心電計の電極をあちこちに付け、血圧計を腕に巻き、自転車を漕ぐ。最初は軽いんだけど、だんだんと重く なって行き、最後は汗だく。年のわりに心臓は丈夫ですねとか言われた。ちゃりんこはお手のものですからね。

でも、心臓のどっきんどっきんには寿命があるとか。約20億回でぽんこつになってしまうらしい。個人差は あるそうだけど。一回のどっきんで、70ccの血液が送り出されるとか。

心拍数が60回/分とすると、一日に8万回どっきんして、6000リットル(ドラム缶33本)の血液が体をめぐるのか。すごい量だな。 せいぜい、どっきんが少なくなるように、安静にしてますかね。夏は特に気をつけましょう。

pickleについて

マーシャリングの要になるやつ。どうなってるか調べてみる。前回どんなデータがファイルに書かれて いたか見た。

(dp0
S'0703.04'
p1
S'123,78,59'
p2
sS'0712.21'
p3
S'119,82,63'
p4
sS'0704.05'
p5
S'128,88,61'
p6
s.

ソースを見ると

MARK            = '('   # push special markobject on stack
STOP            = '.'   # every pickle ends with STOP
STRING          = 'S'   # push string; NL-terminated string argument
PUT             = 'p'   # store stack top in memo; index is string arg
SETITEM         = 's'   # add key+value pair to dict

スタックにデータを積んで、それをメモに移してから構造を作ってるんだな。スタックに一度積むのは、 データが再帰してるのを許容するためか。なる程な。後は、この定数を頼りにソースを追っていくだけだな。 そんなに難しいコードじゃないけど、あちこちに飛んでいるので、飛び回るとちょいと汗をかいてしまうのは、 この時期勘弁願いたい。この間、台風が来た時は、随分と涼しかったので、被害の少ないミニ台風がこないかな。

作ったアプリ

血圧記録アプリに、グラフ機能を追加したんで、開陳してみる。Pythonからさーっとグラフが表示出来て しまうのは嬉しいな。

# blood check

logfile = 'ketu2011.pkl'        # python style object file(keep dict 'dat')

import pickle
import datetime
from pylab import *

dat = {}                         # format  {'mmdd.hh': 'hi,low,pls' ... }
hi = []; low = []; pls = []      # buffer for stat
mm = datetime.date.today().strftime('%m') # this month
dirty = False                    # need to save ?

def save(v=''):
    global dirty
    with open(logfile, 'wb') as pk:
        pickle.dump(dat, pk)
    print('Saved {0} datas!!'.format(len(dat)))
    dirty = False

def load():
    global dat
    with open(logfile, 'rb') as pk:
        dat = pickle.load(pk)
    print('Loaded {0} datas!!'.format(len(dat)))

def sure(v):
    print('{0}: {1}'.format(v, dat[v]))
    ans = raw_input('Sure ? update or del, "yes" to allow ').strip()
    yn = True if ans == 'yes' else False
    return yn

def logging(al):
    global dirty
    a = al.split()
    dh = a.pop(0)
    if len(a) <> 3:
        print('Data is missing !')
        return
    if dh[-3] <> '.': dh = dh[:-2] + '.' + dh[-2:]       # [d]dhh -> [d]d.hh
    mdh = (mm + dh) if len(dh) == 5 else (mm + '0' + dh) # dd.hh or d.hh
    if dat.has_key(mdh):
        if not sure(mdh):
            return
    dat[mdh] = ','.join(a)
    dirty = True

def rm(v):
    global dirty
    if dat.has_key(v):
        if not sure(v):
            return
        del dat[v]
        dirty = True

def sel(x):
    a = dat.keys()
    a.sort()
    if len(x) == 0:                               # all data
        return a
    elif len(x.split()) == 2:                     # between start < stop
        x = x.split()
        return [n for n in a if x[0] < n < x[1] ]
    elif x[-1] == '.':                            # last x.count
        x = x.replace('.', '')
        return a[(-1*int(x)):]
    else:                                         # for mm or mmdd
        return [n for n in a if n.find(x) == 0]

def cat(v=''):
    td = sel(v)
    for k in td:
        v = dat[k].split(',')
        print('{0}  {1}  {2}  {3}'.format(k,v[0],v[1],v[2]))

def expand(v=''):
    td = sel(v)
    global hi,low,pls
    h = []; l = []; p = []
    for k in td:
        a = dat[k].split(',')
        h.append(int(a[0]))
        l.append(int(a[1]))
        p.append(int(a[2]))
    hi = h; low = l; pls =p

def stat(v=''):
    expand(v)
    if len(hi) == 0:
        return
    print('size:   {0}'.format(len(hi)))
    print('min:    {0:5.1f}  {1:5.1f}  {2:5.1f}'.format(min(hi),min(low),min(pls)))
    print('medean: {0:5.1f}  {1:5.1f}  {2:5.1f}'.format(median(hi),median(low),median(pls)))
    print('max:    {0:5.1f}  {1:5.1f}  {2:5.1f}'.format(max(hi),max(low),max(pls)))
    print('mean:   {0:5.1f}  {1:5.1f}  {2:5.1f}'.format(mean(hi),mean(low),mean(pls)))
    print('std:    {0:5.1f}  {1:5.1f}  {2:5.1f}'.format(std(hi),std(low),std(pls)))

def bas(v=''):
    expand(v)
    if len(hi) == 0:
        return
    figure()
    title('Blood transit')
    plot(hi)
    plot(low)
    plot(pls)
    grid(True)          # transit grpha
    figure()
    title('Blood pressure')
    xlabel('Low pressure')
    ylabel('High pressure')
    scatter(low, hi)
    grid(True)          # low vs. hi
    show()

def h3(v=''):
    expand(v)
    if len(hi) == 0: return
    hist([hi,low,pls],20)
    grid(True)
    show()

def b3(v=''):
    expand(v)
    if len(hi) == 0: return
    boxplot([hi,low,pls],0,'rs',0)
    grid(True)
    show()

def mmc(v=''):
    global mm
    if len(v) == 2:
        mm = v

def main():
    global dirty
    cmds = {'save': save, 'cat': cat, 'stat': stat, 'mm': mmc, 'rm': rm,
            'bas': bas, 'hist': h3, 'box': b3, }
    dirty = False
    load()
    try:
        while True:
            al = raw_input((mm + '> ')).strip()
            if len(al) == 0: continue
            if al[0].isdigit():
                logging(al)
            else:
                a = al.split()
                fn = a.pop(0)
                arg= '' if len(a) == 0 else ' '.join(a)
                if cmds.has_key(fn):
                    cmds[fn](arg)
                else:
                    print(cmds.keys())
    except:
        if dirty: save()

if __name__ == '__main__': main()

前回からの変更点

データを入力してく時、d.hh と言うように、日と時刻の間をドットで区切るようにしてた。けど、実際に 使ってみると、ドットを打つのが非常にうざい。で、入力時は、dhhのようにドットを省けるようにした。 たった1行の追加で実現出来た。

cat等で、期間を指定して表示出来るようにした。cat 0625 0704 とすると、6月25日から7月3日までのデータ が選ばれる。

前回は、main()を抜ける時に、無条件でデータをセーブするようにしてた。DISKの寿命を考えて、データに 変化が有った時のみ、セーブするようにした。グローバル変数があちこちに顔を出してしまい、悪い見本に なっちゃったな。

グラフ表示

コマンドbasで表示されるのは、データのトレンドを表示する折れ線グラフ。それと、統計が良く分かった 医者が喜ぶであろう、直交座標による、拡張時血圧(X軸)と縮小時血圧(Y軸)のマッピング。別名、散布図 と言うのかな。

コマンドhistで表示されるのは、ヒストグラムだ。最初、最高血圧、最低血圧、脈拍数を3枚のグラフに したたんだけど、APIを調べていたら、同時に表示出来る事が分かったので、試しにやってみた。 結果は、正規分布とはほど遠いグラフとなってしまったよ。おいらの体って、そんな特異体?

コマンドboxは、統計でよく使われる箱グラフです。サポートしてる事が分かったので試しに使ってみました。 これで、Rの入門版ぐらいは出来そうだな。

グラフ表示のショーケースを見てると、株屋さんが大好きな、ろーそく足も出来るみたいで面白い。 そうそう、コマンドのstatで表示してる統計データも、pylabでは最初からサポートされてて、嬉しいな。 昔、Rubyでやろうとしたら、無くて、いろいろ探し回って、哲也さんとこから貰ってきたよ。懐かしい。

TODO

一度登録したデータを削除するためのコマンドとして、rm を作ったけど、どうも違和感があるなあ。 日時だけを指定したら、削除とみなすようにした方がいいかも。

データの輸出用コマンドが欲しいなあ。CSVにしとけば、何処へでも持って行けるぞ。気分ののったら 追加しておこう。