2015-07-21 48 views
0

我收到了一個從TSV/CSV文件收集數據的循環問題。 問題是我檢查用戶標識符是否在我的tsv文件中,以及是否只是進行常規打印。但事情是它不加起來。運行後停止TSV/CSV文件循環運行

讓我用,我有現在直到代碼解釋一下:

import csv 
with open("source/to/file.tsv") as tsvfile: 
     tsvreader = csv.reader(tsvfile, delimiter="\t") 
     for i in range(1,10): 
      for columns in tsvreader: 
       userid = 1 
       column1, column2, column3 = columns 
       if userid == int(column1): 
        print("userid:", userid,"result: ", int(column1), int(column2), int(column3)) 
        userid += 1 

每當我運行此代碼將輸出:

-- userid: 1 result: 1 3098 1 
-- userid: 1 result: 1 508 1 
-- userid: 1 result: 1 889 1 
-- userid: 1 result: 1 802 0 
-- userid: 1 result: 1 3800 0 

這裏的問題開始。因爲我希望我的用戶ID加到了價值1。我的用戶ID將是2循環將再次啓動,並打印出像:

-- user id 2 result: ... 
-- user id 2 result: ... 
-- user id 2 result: ... 

但我的代碼沒有做到這一點。有人知道爲什麼

請注意:userid 2在我的TSV文件中,所以這不是問題!


額外的信息:在我的TSV文件我有以下情況:

1 802  0 
1 3800 0 
2 7492 1 
2 5235 0 

我要輸出所有屬於userid1(802,3800等)的結果,在那之後循環必須繼續輸出userid2的所有結果(7492,5235等)。在後面的過程中,我想爲每個用戶ID存儲他們的結果。

回答

2

你的代碼不超過1的userid進展Rob's answer解釋原因。

在我看來,你的意圖是打印用戶ID 1的所有行,然後用戶ID 2的所有行,依此類推。並且外部循環的範圍表明您希望顯示用戶ID爲1到9的行。

但是,一個問題是,一旦來自CSV文件的所有行都消耗完畢,for columns in tsvreader循環將不再有任何要迭代的內容過了,所以它的身體不會執行。沒有進一步顯示。這可以通過使用seek()「倒帶」輸入文件來克服。

修復這些錯誤導致這個代碼:

import csv 

with open("source/to/file.tsv") as tsvfile: 
    tsvreader = csv.reader(tsvfile, delimiter="\t") 
    for userid in range(1,10): 
     tsvfile.seek(0) # back to the start of the CSV file 
     for columns in tsvreader: 
      column1, column2, column3 = columns 
      if userid == int(column1): 
       print("userid:", userid,"result: ", int(column1), int(column2), int(column3)) 

認爲這是你所追求的。例如在輸入(我用逗號作爲分隔符):

 
2,4,4 
1,2,3 
1,4,5 
2,8,8 
1,6,7 
2,2,2 
4,1,1 
8,1,2 
10,4,0 
1,0,1 
4,4,4 
3,3,3 

輸出將是:

 
userid: 1 result: 1 2 3 
userid: 1 result: 1 4 5 
userid: 1 result: 1 6 7 
userid: 1 result: 1 0 1 
userid: 2 result: 2 4 4 
userid: 2 result: 2 8 8 
userid: 2 result: 2 2 2 
userid: 3 result: 3 3 3 
userid: 4 result: 4 1 1 
userid: 4 result: 4 4 4 
userid: 8 result: 8 1 2 

注意,對於用戶ID 10中的數據不包括作爲該範圍之外的userids。

我不得不猜測你的意圖,但是,如果我是正確的,你想要做的是按用戶ID分組數據,並按排序順序顯示。更好的方法是簡單地在一個去所有的數據進行排序:

import csv 

with open("source/to/file.tsv") as tsvfile: 
    data = sorted(list(csv.reader(tsvfile, delimiter='\t')), 
        key=lambda row: int(row[0])) 
    for column1, column2, column3 in data: 
     print("userid:", column1, "result: ", int(column1), int(column2), int(column3)) 

輸出:

 
userid: 1 result: 1 2 3 
userid: 1 result: 1 4 5 
userid: 1 result: 1 6 7 
userid: 1 result: 1 0 1 
userid: 2 result: 2 4 4 
userid: 2 result: 2 8 8 
userid: 2 result: 2 2 2 
userid: 3 result: 3 3 3 
userid: 4 result: 4 1 1 
userid: 4 result: 4 4 4 
userid: 8 result: 8 1 2 
userid: 10 result: 11 4 0 

如果你真的要排除一個給定的範圍之外的用戶ID,這樣做:

import csv 

with open("source/to/file.tsv") as tsvfile: 
    data = sorted(list(csv.reader(tsvfile, delimiter='\t')), 
        key=lambda row: int(row[0])) 
    userids = range(1,10) 
    for column1, column2, column3 in data: 
     if int(column1) in userids: 
      print("userid:", column1, "result: ", int(column1), int(column2), int(column3)) 
+0

太棒了!這正是我想要的,解釋非常有幫助!非常感謝! – Rotan075

+0

你也可以告訴我我應該如何輸出每個user_id到一個單獨的csv/tsv文件?或者那是不可能的@mhawke – Rotan075

+0

當然,這是可能的。在遍歷排序的數據時,會跟蹤當前用戶標識。打開一個CSV文件並開始向其寫入每一行。當用戶標識更改時打開一個新的CSV文件並寫入該文件。使用帶有用戶ID的字典作爲鍵可以幫助將列表中每個用戶的數據分組。然後迭代將每個數據寫入文件的字典的鍵。 Burhan Khalid的[答案](http:// stackoverflow。com/a/31538379/21945)使用defaultdict爲每個用戶分組數據 - 您可以將您的代碼關閉。 – mhawke

2

該代碼重置每行的用戶標識符(即在for columns in...循環內)。如果你在該循環之外移動那條線,我相信它會做你想做的。

+0

是的,它會加起來。但問題在於只輸出:1 userid1的結果和1的userid2的結果,我想輸出userid1的所有結果和userid2的所有結果等;) – Rotan075

+0

啊,我看到 - [mhawke的回答](http ://stackoverflow.com/a/31538708/215009)以上涵蓋了這一點。 –

1

我不明白你嘗試做什麼,羅布海牙說你保持userid至1 ...

胡亂猜測你想要什麼:

userid = 1 
tsv = csv.reader(open(filename), delimiter='\t') 
for i, row in enumerate(tsv): 
    if i > 10: 
     break 
    if str(userid) == row[0]: 
     print 'userid: %d result: %s' % (userid, row) 
     userid+= 1 
    else: 
     print 'not found: %s' % (row,) 

編輯

簡單的方法(我不使用示例中的csv模塊,因爲您似乎不需要它),但使用更多的內存。

# load all data 
import collections 

data = collections.defaultdict(list) 

for line in open(filename): 
     row = line.strip().split('\t') 
     data[int(row[0])]+= [row[1:]] 

# output data grouped by user 
for userid, row in data.iteritems(): 
     print 'userid: %d result: %s' % (userid, row) 

另一個簡單的方法(假設數據是排序由用戶ID),儘快使用稍少存儲器outputing結果。

def show(userid, row): 
    print 'userid: %s result: %s' % (userid, row) 

current = '' 
data = [] 
for line in open(filename): 
    row = line.strip().split('\t') 
    if row[0] != current: 
     if data: 
      show(current, data) 
      del data[:] 
     current = row[0] 
    data+=[row] 

show(row[0], data) 

如果數據未排序,你有記憶的問題,你可以存儲在字典中的位置,並通過seek它(見file objects文檔)。

+0

我爲我的問題添加了一些額外的信息。也許你現在明白了吧) – Rotan075

+0

哦,你想通過文件尋找...我會編輯我的文章。 – bufh

+0

謝謝!這確實對我有用! :) – Rotan075

0
1 802  0 
1 3800 0 
2 7492 1 
2 5235 0 

我要輸出所有屬於該結果userid1(802,3800 等),其後的循環必須繼續輸出所有 userid2(7492,5235等)的結果。在後面的過程中,我想爲每個 用戶ID存儲他們的結果。

您可以輕鬆地完成你正在嘗試使用字典來實現的:

import csv 
from collections import defaultdict 

results_by_id = defaultdict(list) 

with open('somefile.csv') as f: 
    reader = csv.reader(f, delimiter='\t') 
    for row in reader: 
     results_by_id[row[0]].append(list(map(int, row[1:]))) 

for userid, results in results_by_id.iteritems(): 
    print('{} has {} total results'.format(userid, len(results))) 
    for result in results: 
     print('\t {}'.format(result)) 
+0

你能解釋這是如何工作的嗎?如何設置用戶ID? – Rotan075