用Python提取唯一的CSV行

1 投票
3 回答
5251 浏览
提问于 2025-04-18 18:52

我正在尝试在Python中获取CSV文件每一行的第一次出现的值。不过,我遇到了一些问题。我的CSV文件看起来是这样的:

1,2,3,a,7,5,y,0
1,2,3,a,3,5,y,8
1,2,3,a,5,3,y,7
1,2,3,d,7,5,n,0
1,2,3,d,3,5,n,8
1,2,3,d,5,3,n,7
2,3,4,f,4,6,y,9
2,3,4,f,5,6,y,9
2,3,4,f,7,3,y,9
2,3,4,e,3,5,n,9
2,3,4,e,0,7,n,9
2,3,4,e,5,8,n,9

我尝试用这种方式来获取基于某一列的唯一值的第一次出现。

def unique():
    rows = list(csv.reader(open('try.csv', 'r'), delimiter=','))
    columns = zip(*rows)
    uniq = set(columns[1])

    indexed = defaultdict(list)

    for x in uniq:
        i = columns[1].index(x)
        indexed[i] = rows[i]

    return indexed

对于一个唯一的列值集,这个方法运行得很好。但是,

  1. 我想把第1列和第6列设置为唯一值。
  2. 比较棘手的是,第6列的值总是'y'或'n'。如果我这样设置,它只会返回第一个'y'和'n'的列。我希望能获取所有同时满足第1列和第6列唯一的列。对于每个第2列的值,我需要得到'y'和'n'行的第一次出现。抱歉我描述得不太清楚。所以基本上,我希望我的输出是这样的:
1,2,3,d,7,5,n,0,a
2,3,4,e,3,5,n,9,f

3 个回答

0

这个话题虽然老旧,但可能对其他人有用:如果你在Unix环境中,为什么不直接使用外部的uniq命令呢?这样你就不用重新写这段代码,还可能获得更好的性能。

1

这里有一个不同的实现方法。

我们从数据集中逐行读取数据。我们使用一个叫做 defaultdict(list) 的工具来存储所有的行,存储的方式是根据每行的两个列的索引来分类。当从数据集中读取到一行时,我们会把这行数据添加到 defaultdict 中,依据的是这行的两个列的索引键。

最后,我们会查看这个 defaultdict。我们想要的是数据集中与索引匹配的 第一 行,所以我们返回 uniq[0],这个对应于两个列的索引。

源代码

import csv
from collections import defaultdict
def unique():
    uniq = defaultdict(list)
    for row in csv.reader(open('try.csv', 'r'), delimiter=','):
        uniq[ (row[0],row[6]) ].append(row)

    for idx,row in uniq.iteritems():
        yield row[0]

print list( unique() )

输出结果

[['2', '3', '4', 'f', '4', '6', 'y', '9'], ['2', '3', '4', 'f', '3', '5', 'n', '9'], ['1', '2', '3', 'a', '7', '5', 'y', '0'], ['1', '2', '3', 'a', '7', '5', 'n', '0']]
3

你的代码还有一些可以改进的地方,不过我不想深入重写,因为你已经做得差不多了。这里的“关键”点是你需要一个复合键。这个复合键就是(r[1],r[6]),它必须是唯一的。此外,我还自作主张地使用了一个OrderedDict,这样可以快速查找,同时保持行的顺序。

import csv
import collections

def unique():
    rows = list(csv.reader(open('try.csv', 'r'), delimiter=','))
    result = collections.OrderedDict()
    for r in rows:
        key = (r[1],r[6])  ## The pair (r[1],r[6]) must be unique
        if key not in result:
            result[key] = r

    return result.values()

from pprint import pprint
pprint(unique())

生成:

[['1', '2', '3', 'a', '7', '5', 'y', '0'],
 ['1', '2', '3', 'a', '7', '5', 'n', '0'],
 ['2', '3', '4', 'f', '4', '6', 'y', '9'],
 ['2', '3', '4', 'f', '3', '5', 'n', '9']]

撰写回答