循环通过TSV / CSV文件在运行后停止

时间:2015-07-21 11:15:23

标签: python csv

我遇到了一个关于从TSV / CSV文件收集数据的循环的问题。 问题是我检查用户ID是否在我的tsv文件中,以及它是否只是进行常规打印。但问题是它没有加起来。

让我通过使用我现在直到的代码来解释自己:

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存储他们的结果。

4 个答案:

答案 0 :(得分:2)

代码重置每行的userid(即for columns in...循环内)。如果你将那条线移到那个循环之外,我相信它会做你想要的。

答案 1 :(得分:2)

Rob's answer中解释了代码未超出用户标识1的原因。

在我看来,您打算打印userid 1的所有行,然后打印userid 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

请注意,不包括用户标识10的数据,因为它超出了用户标识范围。

我不得不猜测你的意图,但是,如果我是正确的,你想要做的是按用户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))

答案 2 :(得分:1)

我没有得到你想要做的事情,因为Rob Hague说你保持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 排序),尽快输出结果并使用稍少的内存。

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文档)。

答案 3 :(得分: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))