データの読み取りと、それに対する処理は分けた方がよいです。
Python
1import csv
2import datetime
3
4# 辞書にデータを読み取る
5date_dict = {}
6with open("moving_train.csv", "r", newline="") as f:
7 reader = csv.reader(f)
8 for row in reader:
9 date = map(int, row[0].split('/'))
10 date_dict[datetime.date(*date)] = int(row[1])
11
12# フィルター用の関数
13def is_in_date_range(date):
14 return datetime.date(2011, 4, 1) <= date < datetime.date(2011, 4, 6)
15
16# 上記関数に適合しない要素を取り除く
17date_dict = dict(filter(lambda x: is_in_date_range(x[0]), date_dict.items()))
18
19"""この時点でのdate_dict (見やすく成形しています)
20{datetime.date(2011, 4, 1): 48,
21 datetime.date(2011, 4, 2): 29,
22 datetime.date(2011, 4, 3): 28,
23 datetime.date(2011, 4, 4): 23,
24 datetime.date(2011, 4, 5): 25}
25"""
26
27total = sum(date_dict.values())
28average = 1.0 * total / len(date_dict)
29print(total, average)
30
31"""実行結果
32153 30.6
33"""
『試したこと』に関しましては、よく理解できなかったのでスルーします。
コメントを受けて
filterは便利な関数なのですが、慣れるまでは意味が分かりづらいかもしれませんね。
簡単に説明すると、次のようになります。
filterは第一引数に関数を、第二引数にリストを取ります。
リストの要素ひとつひとつを関数に渡し、Falseである要素を取り除く働きをします。
以下、簡単な実験コードです。
Python
1>>> def ret_true(arg):
2... return True
3...
4>>> def ret_false(arg):
5... return False
6...
7>>> def over_3(arg):
8... return arg > 3
9...
10>>> my_list = list(range(10))
11>>> my_list
12[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
13>>>
14>>> list(filter(ret_true, my_list))
15[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
16>>>
17>>> list(filter(ret_false, my_list))
18[]
19>>>
20>>> list(filter(over_3, my_list))
21[4, 5, 6, 7, 8, 9]
条件に合わない要素を取り除く働きが分かりますでしょうか。
なお上記の解説は、簡潔な一方で若干不正確です。正確な解説はこちら。
次に、ラムダ式というものを利用して前述の実験コードを書き直してみます。
Python
1>>> my_list = list(range(10))
2>>> my_list
3[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
4>>>
5>>> list(filter(lambda arg: True, my_list))
6[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
7>>>
8>>> list(filter(lambda arg: False, my_list))
9[]
10>>>
11>>> list(filter(lambda arg: arg > 3, my_list))
12[4, 5, 6, 7, 8, 9]
このように、いちいち使い捨てる関数を定義しないで用いることが出来ます。
私のコードでは、ラムダ式と関数とを組み合わせる形でフィルタリングを実現しています。
Python
1# フィルター用の関数
2def is_in_date_range(date):
3 return datetime.date(2011, 4, 1) <= date < datetime.date(2011, 4, 6)
4
5# 上記関数に適合しない要素を取り除く
6date_dict = dict(filter(lambda x: is_in_date_range(x[0]), date_dict.items()))
辞書のアイテム(キーと値)を取り出し、そのキーを関数に与えたときの結果を指標としています。
難しく感じるかもしれませんが、これは慣れもありますので。
結局なにをやっているのか?
Python
1# フィルター用の関数
2def is_in_date_range(date):
3 return datetime.date(2011, 4, 1) <= date < datetime.date(2011, 4, 6)
4
5# 上記関数に適合しない要素を取り除く
6date_dict = dict(filter(lambda x: is_in_date_range(x[0]), date_dict.items()))
次のように書いても、結果は一緒です。
Python
1for key in date_dict:
2 if datetime.date(2011, 4, 1) <= key < datetime.date(2011, 4, 6):
3 pass
4 else:
5 del date_dict[key]
こっちの書き方でも充分簡潔ですね。最初からこっちを書いた方が良かったかも。
Teratailには、コードを上記のように見やすく表示する機能があります。
編集画面を開き、コードを選択した状態で<code>ボタンを押してください。
特にPythonの場合、インデントが崩れるとコードの意味が変わってしまいます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/10/16 08:59
2017/10/16 09:19
2017/10/16 09:23 編集
2017/10/16 11:14