2013-09-05 9 views
1

작동하는 다음 코드를 만들었지 만 그것을 향상시키고 싶습니다. 파일을 다시 읽지는 않겠지 만 sales_input.seek (0)을 삭제하면 판매의 각 행을 반복 실행하지 않습니다. 어떻게 개선 할 수 있습니까?다시로드하지 않고 파이썬에서 csv 파일을 다시 읽음

def computeCritics(mode, cleaned_sales_input = "data/cleaned_sales.csv"): 
    if mode == 1: 
     print "creating customer.critics.recommendations" 
     critics_output = open("data/customer/customer.critics.recommendations", 
           "wb") 
     ID = getCustomerSet(cleaned_sales_input) 
     sales_dict = pickle.load(open("data/customer/books.dict.recommendations", 
             "r")) 
    else: 
     print "creating books.critics.recommendations" 
     critics_output = open("data/books/books.critics.recommendations", 
           "wb") 
     ID = getBookSet(cleaned_sales_input) 
     sales_dict = pickle.load(open("data/books/users.dict.recommendations", 
             "r")) 
    critics = {} 
    # make critics dict and pickle it 
    for i in ID: 
     with open(cleaned_sales_input, 'rb') as sales_input: 
      sales = csv.reader(sales_input) # read new 
      for j in sales: 
       if mode == 1: 
        if int(i) == int(j[2]): 
         sales_dict[int(j[6])] = 1 
       else: 
        if int(i) == int(j[6]): 
         sales_dict[int(j[2])] = 1 
      critics[int(i)] = sales_dict 
    pickle.dump(critics, critics_output) 
    print "done" 

cleaned_sales_input 보이는 숫자 6이 책의 ID이며, 숫자 0이 나는 ​​DICT 느릅 나무의 모양 싶어 고객 ID

입니다

6042772,2723,3546414,9782072488887,1,9.99,314968 
6042769,2723,3546414,9782072488887,1,9.99,314968 
... 

같은

critics = { 
    CustomerID1: { 
     BookID1: 1, 
     BookID2: 0, 
     ........ 
     BookIDX: 0 
    }, 
    CustomerID2: { 
     BookID1: 0, 
     BookID2: 1, 
     ... 
    } 
} 
같은

또는

이 코드 패턴에

것을 우선 보자 :

for i in ID: 
    for j in sales: 
     if int(i) == int(j[2]) 

통지 i 것을는 j[2]와 비교되는 449,661,246,671,771,253,210

나는 여기

+0

csv 읽기가 병목 현상인지 확인하려면 프로필을 작성 했습니까? – RickyA

+0

미안하지만이 프로필이 무엇입니까? 나는 그것에 대해 들어 본 적이 없다. –

+0

[profiler] (http://docs.python.org/2/library/profile.html)는 코드의 각 부분에 소요되는 시간을 확인하는 데 사용됩니다. 이를 통해 코드에서 병목 현상을 식별 할 수 있습니다. 병목 현상이 무엇인지 알지 못하기 때문에 프로필을 작성하기 전에 최적화 작업을 수행하면 거의 쓸모가 없습니다. 어쩌면 여기서 파일 판독이 병목 현상이 아닐 수도 있습니다. – RickyA

답변

2

이되는 사항이 많은 정보에없는 희망 . 그것이 루프의 유일한 목적입니다. int(i) == int(j[2])은 각각 i에 대해 한 번만 True가 될 수 있습니다. ID는 (세트 인 경우 목록 또는 튜플에 반대로

그래서, 우리는 완전히 함수 이름 getCustomerSetgetBookSet을 바탕으로

for j in sales: 
    key = j[2] 
    if key in ID: 

로 재 작성하여 for i in ID 루프를 제거 할 수 있습니다, 그것은 소리). 집합의 테스트 멤버십이 O (1) (목록 또는 튜플의 경우 O (n)과 반대)이므로 ID를 집합으로 지정합니다.

critics[int(i)] = sales_dict 

여기에 잠재적 인 함정이있다 :


다음으로,이 라인을 고려하십시오. 이 줄은 각각 에 을 할당하고 iID입니다. 각 키 int(i)dict과 매우 동일하게 매핑됩니다.

sales_dict[int(j[6])] = 1 

을하지만이 동일한 딕셔너리를 critics 지점에서 모든 키 때문에, 동시에 수정할 critics모든 값을 초래할 것이다 salesID 통해 우리 루프로서, 우리는 예를 들면, 이런 sales_dict을 수정 , sales_dict. 나는 그것이 당신이 원하는 것이라고 의심합니다.unutbu의 대답 @

critics = {i:sales_dict.copy() for i in ID} 

def computeCritics(mode, cleaned_sales_input="data/cleaned_sales.csv"): 
    if mode == 1: 
     filename = 'customer.critics.recommendations' 
     path = os.path.join("data/customer", filename) 
     ID = getCustomerSet(cleaned_sales_input) 
     sales_dict = pickle.load(
      open("data/customer/books.dict.recommendations", "r")) 
     key_idx, other_idx = 2, 6 
    else: 
     filename = 'books.critics.recommendations' 
     path = os.path.join("data/books", filename)   
     ID = getBookSet(cleaned_sales_input) 
     sales_dict = pickle.load(
      open("data/books/users.dict.recommendations", "r")) 
     key_idx, other_idx = 6, 2 

    print "creating {}".format(filename) 
    ID = {int(item) for item in ID} 
    critics = {i:sales_dict.copy() for i in ID} 
    with open(path, "wb") as critics_output: 
     # make critics dict and pickle it 
     with open(cleaned_sales_input, 'rb') as sales_input: 
      sales = csv.reader(sales_input) # read new 
      for j in sales: 
       key = int(j[key_idx]) 
       if key in ID: 
        other_key = int(j[other_idx]) 
        critics[key][other_key] = 1      
       critics[key] = sales_dict 
     pickle.dump(dict(critics), critics_output) 
     print "done" 
+0

미안하지만 그것을 추가하고 싶지는 않지만 C = {ID1 {Book : 1, Book : 0 ........ Book : 0}, ID2 .....}처럼 보이는 dict을 만들고 싶습니다. 이쪽으로 가야합니까 아니면 그냥 막혀 있습니까? –

+2

코드와 dict 사이에는 명백한 관계가 없습니다. 당신은 당신의 질문에 답하기 전에'ID'와 똑같은 내용과'cleaned_sales_input'의 샘플을 채워야합니다. – unutbu

+0

나는 더 많은 정보를 추가했다. –

0

이 더 있지만,이 구조로 붙어있는 경우가 전체 파일을 넣을 수 있습니다 :

이 함정을 피하기 위해, 우리는 sales_dict의 사본을 만들 필요가 메모리에 :

sales = [] 
with open(cleaned_sales_input, 'rb') as sales_input: 
    sales_reader = csv.reader(sales_input)  
    [sales.append(line) for line in sales_reader] 

    for i in ID: 
     for j in sales: 
      #do stuff 
관련 문제