用Python高效合并CSV中具有单个重复字段的行的方法是什么?

2 投票
2 回答
3349 浏览
提问于 2025-04-18 03:17

我看到了一些类似的问题,不过那些我觉得可能有用的答案对我来说太复杂了,没法直接用上。我需要一些帮助,来弄清楚如何在Python中完成以下任务:

我有一个CSV文件,里面有三列数据。在第一列中,有一些重复的值(也就是说在其他行中也出现过),我需要把这些重复的值合并成一行,同时把第二列和第三列的特定数据也合并到这一行中。最终的结果应该是另一个CSV文件。

此外,对于每一组有重复第一列数据的行,第二列和第三列的数据有很多情况需要合并。换句话说,对于第一列的每个值,如果第二列的值不为空,就把它抓取过来放到“最终”行的第二列;如果第二列为空,就抓取第三列的值放到“最终”行的第三列。我需要遵循的规则是:第一列值的第一和最后一次出现需要合并所有存在的第二列和第三列数据,同时保持第二列的数据在第二列中,第三列的数据在第三列中。而且在源CSV的每一行中,永远不会有三个完整的值。

为了更好地解释,以下是源CSV中数据的排列情况:这些是需要合并的源CSV中的行的示例:

示例1:这里我有四行匹配的第一列数据,对于所有示例,我需要的结果是一行,包含第一列的值,后面跟着第一和最后一次出现的第一列值对应的值。

wp.xyz03.def02.01195.1,wp03.xyz03-c01_lc08_m00,
wp.xyz03.def02.01195.1,wp02.xyz03,
wp.xyz03.def02.01195.1,,wp01.def02
wp.xyz03.def02.01195.1,,wp02.def02-c02_lc14_m00

所以这个组的期望结果是:

wp.xyz03.def02.01195.1,wp03.xyz03-c01_lc08_m00,wp02.def02-c02_lc14_m00

示例2:这里我有三行匹配的第一列数据,同样我需要的结果是一行,包含第一列的值,后面跟着第一和最后一次出现的第一列值对应的值。

wp.atl21.lmn01.01193.2,wp03.atl21-c06_lc14_m00,
wp.atl21.lmn01.01193.2,wp02.atl21,
wp.atl21.lmn01.01193.2,,wp03.lmn01

所以这个组的期望结果是:

wp.atl21.lmn01.01193.2,wp03.atl21-c06_lc14_m00,wp03.lmn01

示例3:这里我有三行匹配的第一列数据,同样我需要的结果是一行,包含第一列的值,后面跟着第一和最后一次出现的第一列值对应的值。注意这个例子中,第一行的第二列现在没有值,而是想要的值在第三列。

tp.ghi03.ghi05.02194.65,,tp05.ghi05:1
tp.ghi03.ghi05.02194.65,tp05.ghi03:2,
tp.ghi03.ghi05.02194.65,tp05.ghi03-c06_lc11_m00,

所以这个组的期望结果是:

tp.ghi03.ghi05.02194.65,tp05.ghi03-c06_lc11_m00,tp05.ghi05:1

把所有内容放在一起:

这个:

wp.xyz03.def02.01195.1,wp03.xyz03-c01_lc08_m00,
wp.xyz03.def02.01195.1,wp02.xyz03,
wp.xyz03.def02.01195.1,,wp01.def02
wp.xyz03.def02.01195.1,,wp02.def02-c02_lc14_m00
wp.atl21.lmn01.01193.2,wp03.atl21-c06_lc14_m00,
wp.atl21.lmn01.01193.2,wp02.atl21,
wp.atl21.lmn01.01193.2,,wp03.lmn01
tp.ghi03.ghi05.02194.65,,tp05.ghi05:1
tp.ghi03.ghi05.02194.65,tp05.ghi03:2,
tp.ghi03.ghi05.02194.65,tp05.ghi03-c06_lc11_m00,

需要变成这个:

wp.xyz03.def02.01195.1,wp03.xyz03-c01_lc08_m00,wp02.def02-c02_lc14_m00
wp.atl21.lmn01.01193.2,wp03.atl21-c06_lc14_m00,wp03.lmn01
tp.ghi03.ghi05.02194.65,tp05.ghi03-c06_lc11_m00,tp05.ghi05:1

我尝试了很多方法来实现这个,但我无法在不进入非常陌生的领域的情况下达到想要的结果。

这是我最初的尝试,结果导致一些必要的值被截断,因为一旦我达到三个值,它就会写出,而从未捕捉到可能还有其他值:

reader = csv.reader(open('parse_lur_luraz_clean_temp.csv', 'r'), delimiter=',')
final = ['-','-','-']
parselur = ['-']
lur_a = ""
lur_z = ""
for row in reader:
    if row[0] != parselur[0]:
        final = ['-','-','-']
        if row[1] != '': lur_a = row[1]
        if row[2] != '': lur_z = row[2]
        parselur[0] = row[0]
    elif row[0] == parselur[0]:
        if row[1] == '':
            lur_a = row[1]
        elif row[1] != '':
            lur_a = row[1]
        if row[2] == '':
            lur_z = row[2]
        elif row[2] != '':
            lur_z = row[2]
        parselur[0] = row[0]
    if parselur[0] != '' and parselur[0] not in final: final[0] = parselur[0]
    if lur_a != '': 
        if final[1] == '-' or '_lc' not in final[1]: final[1] = lur_a
        lur_a = ''
    if lur_z != '': 
        if final[2] == '-' or '_lc' not in final[2]: final[2] = lur_z
        lur_z = ''
    if len(final) == 3 and '-' not in final:
        fd = open('final_alu_nsn_temp.csv','a')
        writer = csv.writer(fd)
        writer.writerow((final))
        fd.close()
        final = ['-','-','-']
    else:
        parselur[0] = row[0]

2 个回答

0

如果我理解你想做的事情,下面是一些伪代码:

Read each line:
Split by comma
Add each section to a large list

Next

Until list is empty:

Foreach value in the list:
Write value to file, then write a comma
Search a list, and remove duplicate values

这样可以吗?如果这是你想要的,我可以为你写一个Python程序。

补充:

我写了一个程序,按照我看到的,你给我的示例输入变成了示例输出。

FileInput = open("Input.txt") #Open an input file
EntireFile = FileInput.read() #Read to the end of the file

EntireFile = EntireFile.replace("\n","").replace("\r","")
#Remove newline characters

SplittedByComma = EntireFile.split(",")
#Split into a list

FileOutput = open("Output.txt","w") #The output file

#Go through the list. For each element, remove other ones that are the same
for X in SplittedByComma:
    for Y in range(len(SplittedByComma)-1,0,-1):
        if (X == SplittedByComma[Y]):
            SplittedByComma.pop(Y)

Output = "" #This will eventually get written to the file

for X in SplittedByComma:
    Output +=X + ","

#Write output, but dont write the last character (So it doesn't end on a comma)
FileOutput.write(Output[:-1])
FileOutput.close()
#Close the file so it saves

如果你有任何问题,随时问我。

2

现在正是学习 itertools.groupby 的好时机:

import csv
from itertools import groupby

# assuming Python 2
with open("source.csv", "rb") as fp_in, open("final.csv", "wb") as fp_out:
    reader = csv.reader(fp_in)
    writer = csv.writer(fp_out)
    grouped = groupby(reader, lambda x: x[0])
    for key, group in grouped:
        rows = list(group)
        rows = [rows[0], rows[-1]]
        columns = zip(*(r[1:] for r in rows))
        use_values = [max(c) for c in columns]
        new_row = [key] + use_values
        writer.writerow(new_row)

会产生

$ cat final.csv 
wp.xyz03.def02.01195.1,wp03.xyz03-c01_lc08_m00,wp02.def02-c02_lc14_m00
wp.atl21.lmn01.01193.2,wp03.atl21-c06_lc14_m00,wp03.lmn01
tp.ghi03.ghi05.02194.65,tp05.ghi03-c06_lc11_m00,tp05.ghi05:1

撰写回答