在Python itertools groupby中令人不安的奇怪行为/错误?

时间:2012-10-24 00:00:58

标签: python parsing csv text-parsing itertools

我正在使用itertools.groupby来解析一个以制表符分隔的短文本文件。文本文件有几列,我想要做的就是将特定列中具有特定值x的所有条目分组。下面的代码针对名为name2的列执行此操作,查找变量x中的值。我尝试使用csv.DictReaderitertools.groupby执行此操作。在表中,有 8 行符合此条件,因此应返回8个条目。相反,groupby返回两组条目,一组具有单个条目,另一组具有7,这似乎是错误的行为。我在下面手动对相同数据进行匹配,得到正确的结果:

import itertools, operator, csv
col_name = "name2"
x = "ENSMUSG00000002459"
print "looking for entries with value %s in column %s" %(x, col_name)
print "groupby gets it wrong: "
data = csv.DictReader(open(f), delimiter="\t", fieldnames=fieldnames)
for name, entries in itertools.groupby(data, key=operator.itemgetter(col_name)):
    if name == "ENSMUSG00000002459":
        wrong_result = [e for e in entries]
        print "wrong result has %d entries" %(len(wrong_result))
print "manually grouping entries is correct: "
data = csv.DictReader(open(f), delimiter="\t", fieldnames=fieldnames)
correct_result = []
for row in data:
    if row[col_name] == "ENSMUSG00000002459":
        correct_result.append(row)
print "correct result has %d entries" %(len(correct_result))

我得到的输出是:

looking for entries with value ENSMUSG00000002459 in column name2
groupby gets it wrong: 
wrong result has 7 entries
wrong result has 1 entries
manually grouping entries is correct: 
correct result has 8 entries

这里发生了什么?如果groupby确实是分组,那么我似乎每个x只能获得一组条目,而是返回两个条目。我无法弄清楚这一点。 编辑:啊得到它应该排序。

3 个答案:

答案 0 :(得分:3)

根据documentationgroupby()组仅连续出现相同的密钥。

答案 1 :(得分:3)

您将要更改代码以强制数据按键顺序...

data = csv.DictReader(open(f), delimiter="\t", fieldnames=fieldnames)
sorted_data = sorted(data, key=operator.itemgetter(col_name))
for name, entries in itertools.groupby(data, key=operator.itemgetter(col_name)):
    pass # whatever

主要用途是,当数据集很大且数据已按键顺序排列时,所以当你必须进行排序时,使用defaultdict会更有效率

from collections import defaultdict
name_entries = defaultdict(list)
for row in data:
    name_entries[row[col_name]].append(row)

答案 2 :(得分:2)

我不知道您的数据是什么样的,但我的猜测是它没有排序。 groupby works on sorted data