使用部分列在Python中去除重复项

0 投票
5 回答
2581 浏览
提问于 2025-04-18 15:19

我有一个用制表符分隔的输入文件 input.txt,内容如下:

A    B    C
A    B    D
E    F    G
E    F    T
E    F    K

这些数据是用制表符分开的。

我想要删除重复的行,但只有当多行的第一列和第二列相同时才删除。

所以,即使第一行和第二行的第三列不同,只要它们的第一列和第二列相同,我就想删除后面出现的那一行,比如 "A B D"。

所以,输出文件 output.txt 应该是这样的:

A    B    C
E    F    G

如果我想用普通的方法去掉重复项,我只需要把列表变成一个“集合”(set),这样就可以了。

但现在我想用“某些”列来去重。

在 Excel 中,这个操作非常简单。

数据 -> 删除重复项 -> 选择列

在 MatLab 中也很简单。

导入 input.txt -> 使用“unique”函数针对第一列和第二列 -> 删除编号为“1”的行

但是在 Python 中,我找不到怎么做,因为我只知道用“set”来去重。

===========================

这是我根据 undefined_is_not_a_function 的回答进行的实验。

我不确定怎么把结果覆盖到 output.txt,也不知道怎么修改代码来让我指定用于去重的列(比如第三列和第五列)。

import sys
input = sys.argv[1]

seen = set()
data = []
for line in input.splitlines():
    key = tuple(line.split(None, 2)[0])
    if key not in seen:
        data.append(line)
        seen.add(key)

5 个回答

0

请注意,我不是专家,但我还是有一些想法可能对你有帮助。

有一个叫做csv的模块专门用来处理csv文件,你可以去看看,或许会有一些有趣的东西。

首先,我想问问你是怎么存储这些数据的?是用列表吗?

像这样:

[[A,B,C],
[A,B,D],
[E,F,G],...]

这可能是合适的选择。(也许不是最好的选择)

其次,能否遍历整个列表呢?

你可以简单地存储一行,然后把它和所有行进行比较。

我会这样做:假设列表里包含字母。

copy = list
index_list = []
for i in range(0, len(list)-1):
    for j in range(0, len(list)-1): #and exclude i of course
     if copy[i][1] == list[j][1] and copy[i][0] == list[j][0] and i!=j:
          index_list.append(j)
for i in index_list: #just loop over the index list and remove
list.pop(index_list[i])

这不是有效的代码,但它给你提供了一个思路。这是完成你任务的最简单方法,可能不是最合适的选择。(而且这会花费一些时间,因为你需要进行平方数量的操作)。

补充一下:用pop,而不是remove。

0

假设你已经读取了你的对象,并且你有一个叫做 rows 的数组(如果你需要帮助可以告诉我),下面的代码应该可以正常运行:

entries = set()
keys = set()
for row in rows:
   key = (row[0], row[1]) # Only the first two columns

   if key not in keys:
      keys.add(key)
      entries.add((row[0], row[1], row[2]))
0

从下面的代码,你可以做到这一点。

file_ = open('yourfile.txt')
lst = []
for each_line in file_ .read().split('\n'):
    li = each_line .split()
    lst.append(li)
dic = {}
for l in lst:
    if (l[0], l[1]) not in dic:
        dic[(l[0], l[1])] = l[2]

print dic

抱歉,变量名可能不太好理解。

2

如果你能使用Unix系统,里面有一个叫做sort的工具,非常适合解决你的问题。

sort -u -t$'\t' --key=1,2 filein.txt

我知道这是一个关于Python的问题,但有时候Python并不是解决这个问题的最佳工具。而且你总是可以在你的Python脚本中调用系统命令。

4

你应该使用 itertools.groupby 来处理这个问题。在这里,我是根据前两列的数据进行分组,然后用 next() 来获取每个组的第一个项目。

>>> from itertools import groupby                                   
>>> s = '''A    B    C                                              
A    B    D
E    F    G
E    F    T
E    F    K'''
>>> for k, g in groupby(s.splitlines(), key=lambda x:x.split()[:2]):
    print next(g)
...     
A    B    C
E    F    G

如果输入数据来自文件,只需把 s.splitlines() 替换成文件对象就可以了。


请注意,上面的解决方案只有在数据按照前两列排序的情况下才有效。如果数据没有排序,那么你需要在这里使用 set

>>> from operator import itemgetter
>>> ig = itemgetter(0, 1) #Pass any column number you want, note that indexing starts at 0
>>> s = '''A    B    C
A    B    D
E    F    G
E    F    T
E    F    K
A    B    F'''     
>>> seen = set()
>>> data = []
>>> for line in s.splitlines():
...     key = ig(line.split())
...     if key not in seen:
...         data.append(line)
...         seen.add(key)
...         
>>> data
['A    B    C', 'E    F    G']

撰写回答