プロが教える店舗&オフィスのセキュリティ対策術

pythonで実績データの解析プログラムを作ったんですが処理が遅くてなかなか使い勝手が悪いんです。処理を早くしようと書き直したいんですが、頭が固まっちゃってうまい案が出てこないんです。
csvファイル形式で一行目がカラム名、10列あって2列目に日付[カラム名でymd]で、形式は2007-05-01という感じです。10列目に人数[カラム名amt]があり、来店人数を日別ごとの小計で出したいんです。
日付 小計
日付 小計
  :
こんな感じです。
一応プログラムはこんな感じです。

#!/usr/bin/env python
import time
t1 = time.time()
def readcsv(filename):
L = [line[:-1] for line in file(filename).readlines()]
return map((lambda s: s.split(',')), L)
csvlist = readcsv(./csv.csv')
totalamt = {}
for line in csvlist[1:]:
buydict = dict(zip(csvlist[0], line))
if 'ymd' in buydict.keys():
if not buydict['ymd'] in totalamt:
totalamt[buydict['ymd']] = 0
totalamt[buydict['ymd']] += int(buydict['amt'])
for k in sorted(totalamt.keys()):
print '%s , %d' % (k, totalamt[k])
t2 = time.time()
print t2 - t1, 'sec'

結果はちゃんと出るんですが、遅いんです。
処理速度を早くしたいんです。誰かご教授御願いします。

A 回答 (2件)

http://okwave.jp/qa5421190.html
と同じ内容で、違うIDなのはなぜなんでしょうか?

遅いから早くしたいということですが、どのくらいのデータを食わせて
現状どのくらいの時間がかかり、それをどのくらい改良したいのでしょうか?

以前 C/C++ カテゴリにあったものから判断して

import random
def make_record(y, m, d):
__return ",".join([str(x) for x in ((random.randint(20,30)),
____________________________________"%4d-%02d-%02d" % (y, m, d),
____________________________________random.randint(1, 3),
____________________________________random.randint(0, 99),
____________________________________"%03d" % random.randint(11, 18),
____________________________________random.randint(100, 999))])

print "shop,ymd,gend,age,area,amt"
for y in range(2008,2009):
__for m in range(1, 13):
______for d in range(1, 31):
__________for i in range(0, 1000):
______________print make_record(y, m, d)

こんなんで適当にデータをでっち上げて試してみましたが

#!/usr/bin/env python
import sys
import time
t1 = time.time()

def readcsv(filename):
__L = [line[:-1] for line in file(filename).readlines()]
__return map((lambda s: s.split(',')), L)


csvlist = readcsv('./csv.csv')
totalamt = {}

currentmonth = ""
subtotal = 0

t2 = time.time()
print >>sys.stderr, t2 - t1, 'sec'

#sys.exit()
for line in csvlist[1:]:
__#1
__#buydict = dict(zip(csvlist[0], line))
__#if 'ymd' in buydict.keys():
__#____if not buydict['ymd'] in totalamt:
__#________totalamt[buydict['ymd']] = 0
__#____totalamt[buydict['ymd']] += int(buydict['amt'])
__#2
__#if not line[1] in totalamt:
__#____totalamt[line[1]] = 0
__#totalamt[line[1]] += int(line[-1])
__#3
__if currentmonth <> line[1]:
______if currentmonth <> "":
__________print '%s , %d' % (currentmonth, subtotal)
______currentmonth = line[1]
______subtotal = 0
__subtotal += int(line[-1])

#3 の場合のみ不要
#for k in sorted(totalamt.keys()):
#____print '%s , %d' % (k, totalamt[k])

で10メガバイト前後のデータを処理させてみたところ

パターン1
1.71900010109 sec
6.17199993134 sec

1.71799993515 sec
6.17199993134 sec

1.71900010109 sec
6.18800020218 sec

パターン2
1.7349998951 sec
2.82799983025 sec

1.71899986267 sec
2.79699993134 sec

1.70300006866 sec
2.79699993134 sec

パターン3
1.71899986267 sec
2.64100003242 sec

1.70299983025 sec
2.625 sec

1.70300006866 sec
2.625 sec

こんな感じでした。
いずれにしても情報が少なすぎですね。
    • good
    • 0

python は使っていないけど, このプログラムで時間がかかりそうなのは


・ファイルを読み込むときに全体を一度に読み込んでいる
・連想配列 (辞書) を使っている
ところかな. 前者については「1行ずつ読み込んでそのたびに処理をする」, 後者については (必要なフィールドがどこかをあらかじめ調べておいて) 「配列要素の参照に置き換える」と速くなるかもしれません.
いずれにしても, 現在のプログラムで「どこで時間がかかっているのか」をまず把握する必要があると思います. その上で「どこに手を加えるか」を考えないと, 労力のわりに効果が出ないことはよくあります.

この回答への補足

配列要素の参照ですか?
うーん、勉強不足なのでいまいち理解できないんですが。もう少し調べてみます。pythonに触れ始めて1週間なもので、なかなか理解が追いつかなくて。
 今回のプログラムでは、日付別に足さなきゃいけなかったので、日付をキーとした辞書を使って足す、という方法しか日付分けのしかたを考え付かなかったんです。
 あとは、1行づつ読み込んで処理する方法も考えてみます。

補足日時:2009/11/04 17:41
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!