ThinkStats (7)
棒グラフ二つ描くソレはスルーで。つうかコード配布してる、って先で書いてあるのを発見。そりゃ良いとして演習問題に着手。
演習問題 2-4
書いてる事はよく分からんけど、単純にプログラムする問題ととらえてヤッツケることに。例えば第一子の Pmf は以下なカンジなんですが
>>> pmf.GetDict() {0: 0.00022660321776569228, 17: 0.00022660321776569228, 20: 0.00022660321776569228, 21: 0.00022660321776569228, 22: 0.0006798096532970768, 23: 0.00022660321776569228, 24: 0.0015862225243598459, 25: 0.00022660321776569228, 26: 0.0036256514842510764, 27: 0.00022660321776569228, 28: 0.005438477226376614, 29: 0.0020394289598912306, 30: 0.016542034896895538, 31: 0.003399048266485384, 32: 0.012463176977113076, 33: 0.0063448900974393836, 34: 0.006571493315205076, 35: 0.03602991162474507, 36: 0.03897575345569907, 37: 0.04713346929526399, 38: 0.0616360752322683, 39: 0.47903920235667347, 40: 0.12145932472241106, 41: 0.08157715839564922, 42: 0.04645365964196692, 43: 0.01971447994561523, 44: 0.005211874008610923, 45: 0.0013596193065941536, 46: 0.00022660321776569228, 47: 0.00022660321776569228, 48: 0.0006798096532970768}
使用年数が 35 とするとそこまでのナニを削除して再度正規化 (Normalize) というか辞書から Pmf を作れば良いはず。中身を見るに Normalize してますね。
pmf = Pmf(d, name) pmf.Normalize() return pmf
ということは算数と言うよりは Python の辞書の扱いな問題、ってことになりますね。つうことは
for k, v in dic.iteritems():
で両方取ってきて、k が使用年数より大きければ k - 使用年数と v を新しい辞書に設定すれば良いのか。以下なカンジ?
def PmfRemainingLifetime(y, pmf): newDic = {} for k, v in pmf.GetDict().iteritems(): if y < k: newDic[k - y] = v return Pmf.MakePmfFromDic(newDic)
本当かなぁ。例えば 5 年で必ず壊れるある機械があって、以下の頻度で壊れてる実績があるとすると
(10 10 10 10 10)
大体 2 割程度の確率で壊れてくって凄い話ですがスルーで。そうか年数を経る毎に死んじゃう確率自体は上がるのかw
最初の PMF は (0.2 0.2 0.2 0.2 0.2) で、3 年経っちゃうと (0.5 0.5) になると。試験を書いてみますね (先に試験から)。
import Pmf import PmfRemainingLifetime import unittest class TestPmfRemainingLifetime(unittest.TestCase): def test_PmfRemainingLifetime(self): pmf = Pmf.MakePmfFromDict({0: 0.2, 1: 0.2, 2: 0.2, 3: 0.2, 4: 0.2}) newPmf = PmfRemainingLifetime.PmfRemainingLifetime(2, pmf) self.assertEqual([0.5, 0.5], newPmf.Items()) if __name__ == '__main__': unittest.main()
で、実行。
$ python PmfRemainingLifetime_test.py Traceback (most recent call last): File "PmfRemainingLifetime_test.py", line 2, in <module> import PmfRemainingLifetime ImportError: No module named PmfRemainingLifetime
ファイルが無い。touch してみるか。
$ touch PmfRemainingLifetime.py $ python PmfRemainingLifetime_test.py E ====================================================================== ERROR: test_PmfRemainingLifetime (__main__.TestPmfRemainingLifetime) ---------------------------------------------------------------------- Traceback (most recent call last): File "PmfRemainingLifetime_test.py", line 8, in test_PmfRemainingLifetime newPmf = PmfRemainingLifetime.PmfRemainingLifetime(2, pmf) AttributeError: 'module' object has no attribute 'PmfRemainingLifetime' ---------------------------------------------------------------------- Ran 1 test in 0.000s FAILED (errors=1)
メソドが無い。ええと、ここまで書いてようやくまともな FAILED になりました。
import Pmf def PmfRemainingLifetime(y, pmf): return Pmf.Pmf()
出力が以下。
$ python PmfRemainingLifetime_test.py F ====================================================================== FAIL: test_PmfRemainingLifetime (__main__.TestPmfRemainingLifetime) ---------------------------------------------------------------------- Traceback (most recent call last): File "PmfRemainingLifetime_test.py", line 9, in test_PmfRemainingLifetime self.assertEqual([0.5, 0.5], newPmf.Items()) AssertionError: Lists differ: [0.5, 0.5] != [] First list contains 2 additional elements. First extra element 0: 0.5 - [0.5, 0.5] + [] ---------------------------------------------------------------------- Ran 1 test in 0.000s FAILED (failures=1)
馬鹿なことしてないでさっさと進めますね。盛り込んでみると失敗。
AttributeError: 'module' object has no attribute 'MakePmfFromDic'
MakePmfFromDict でした (汗
で、しかも Items はリストのリストを戻してるなorz
assert を以下に修正して試験パス。
self.assertEqual([(1, 0.5), (2, 0.5)], newPmf.Items())
なんか gdgd だorz
演習問題 2-5
どんどん進めます。つうかこれ、面白いですね。
(+ (* 1 0.2) (* 0.2 2) (* 0.2 3) (* 0.2 4) (* 0.2 5)) 3.0
と
(/ (+ (* 1 10) (* 2 10) (* 3 10) (* 4 10) (* 5 10)) 50) 3
なのか。むむむ。まず算術平均が以下。
import Pmf def PmfMean(pmf): ret = 0 for k, v in pmf.GetDict().iteritems(): ret += k * v return ret
試験が以下でパスしてます。
import Pmf import PmfMean import unittest class TestPmfMean(unittest.TestCase): def test_PmfMean(self): p = Pmf.MakePmfFromDict({1: 0.2, 2: 0.2, 3: 0.2, 4: 0.2, 5: 0.2}) self.assertEqual(3, PmfMean.PmfMean(p)) if __name__ == '__main__': unittest.main()
あ、試験はこう書くのか。
self.assertEqual(p.Mean(), PmfMean.PmfMean(p))
次、PmfVar は以下かな。
import Pmf def PmfVar(pmf): ret = 0 mu = pmf.Mean() for k, v in pmf.GetDict().iteritems(): ret += ((k - mu) ** 2) * v return ret
試験書くのが楽でいいですね。
import Pmf import PmfVar import unittest class TestPmfVar(unittest.TestCase): def test_PmfVar(self): p = Pmf.MakePmfFromDict({1: 0.2, 2: 0.2, 3: 0.2, 4: 0.2, 5: 0.2}) self.assertEqual(p.Var(), PmfVar.PmfVar(p)) if __name__ == '__main__': unittest.main()
2 章残りに目を通す方向。あ、電話しなきゃ、なんだった。続きがあればこのまま追記の方向です。
演習問題 2-6
中身はスルー。月曜朝とかで確認の方向。Python の辞書ってキーが数値ならその順で取り出せるのかな。それ前提でいくと話は早い。
以下をでっちあげて
import Pmf def ProbCommon(f, t, p): ret = 0 for k, v in p.GetDict().iteritems(): if (f <= k) and (k <= t): ret += v return ret def ProbEarly(p): return ProbCommon(0, 37, p) def ProbOnTime(p): return ProbCommon(38, 40, p) def ProbLate(p): return ProbCommon(41, 99, p)
REPL で確認。
>>> import Pmf >>> import thinkstats >>> import survey >>> table = survey.Pregnancies() >>> table.ReadRecords() >>> first_p = [] >>> other_p = [] >>> >>> for i in table.records: ... if i.outcome == 1: ... if i.birthord == 1: ... first_p.append(i.prglength) ... else: ... other_p.append(i.prglength) ... >>> first_pmf = Pmf.MakePmfFromList(first_p) >>> other_pmf = Pmf.MakePmfFromList(other_p) >>> first_pmf <Pmf.Pmf object at 0x7fb605bcaf90> >>> import risk >>> risk.ProbEarly(first_pmf) 0.18241559030138227 >>> risk.ProbEarly(other_pmf) 0.16832101372756073
あとは正解コードを確認することにして先に進もう。