【问题标题】:Working with csv files in python - sort and fill values在 python 中处理 csv 文件 - 排序和填充值
【发布时间】:2022-01-26 17:10:39
【问题描述】:

我想根据 BookID 填充缺失的信息:MissingAuthor 和 MissingLanguage - 如果 BookID 是同一个副本,并填写您找到它的信息。

输入 CSV 文件:

input.csv
BookName,BookID,BookLocation,BookAuthor,BookLanguage
BookA,19821,C216,Guido van Rossum,English
BookB,19821,C216,AuthorMissing,English
BookC,15351,C126,Eric Matthes,LanguageMissing
BookD,15551,C446,AuthorMissing,English
BookE,15351,C126,AuthorMissing,English
BookF,15551,C446,Al Sweigart,LanguageMissing
BookG,21221,C556,AuthorMissing,English
BookH,21221,C556,Mark Lutz,English
BookI,14421,C656,Eric Matthes,English
BookJ,14421,C656,Eric Matthes,LanguageMissing
BookK,55521,C776,AuthorMissing,English
BookL,55521,C776,Mark Lutz,LanguageMissing
BookM,16721,C886,Al Sweigart,English
BookN,16721,C886,AuthorMissing,English
BookO,16721,C996,Al Sweigart,LanguageMissing

举个例子:

input:
BookA,19821,C216,Guido van Rossum,English
BookB,19821,C216,AuthorMissing,English

output:
BookA,19821,C216,Guido van Rossum,English
BookB,19821,C216,Guido van Rossum,English <--- AuthorMissing

代码:

import csv

with open('input.csv', 'r') as incsv:
    reader = csv.DictReader(incsv, delimiter=',')
    header = next(reader)
    sortedbyid = sorted(reader, key=lambda row: (row['BookID']), reverse=False) # sort by BookID
    for line in sortedbyid:
        print(line)
{'BookName': 'BookI', 'BookID': '14421', 'BookLocation': 'C656', 'BookAuthor': 'Eric Matthes', 'BookLanguage': 'English'}
{'BookName': 'BookJ', 'BookID': '14421', 'BookLocation': 'C656', 'BookAuthor': 'Eric Matthes', 'BookLanguage': 'LanguageMissing'}
{'BookName': 'BookC', 'BookID': '15351', 'BookLocation': 'C126', 'BookAuthor': 'Eric Matthes', 'BookLanguage': 'LanguageMissing'}
{'BookName': 'BookE', 'BookID': '15351', 'BookLocation': 'C126', 'BookAuthor': 'AuthorMissing', 'BookLanguage': 'English'}
{'BookName': 'BookD', 'BookID': '15551', 'BookLocation': 'C446', 'BookAuthor': 'AuthorMissing', 'BookLanguage': 'English'}
{'BookName': 'BookF', 'BookID': '15551', 'BookLocation': 'C446', 'BookAuthor': 'Al Sweigart', 'BookLanguage': 'LanguageMissing'}
{'BookName': 'BookM', 'BookID': '16721', 'BookLocation': 'C886', 'BookAuthor': 'Al Sweigart', 'BookLanguage': 'English'}
{'BookName': 'BookN', 'BookID': '16721', 'BookLocation': 'C886', 'BookAuthor': 'AuthorMissing', 'BookLanguage': 'English'}
{'BookName': 'BookO', 'BookID': '16721', 'BookLocation': 'C996', 'BookAuthor': 'Al Sweigart', 'BookLanguage': 'LanguageMissing'}
{'BookName': 'BookB', 'BookID': '19821', 'BookLocation': 'C216', 'BookAuthor': 'AuthorMissing', 'BookLanguage': 'English'}
{'BookName': 'BookG', 'BookID': '21221', 'BookLocation': 'C556', 'BookAuthor': 'AuthorMissing', 'BookLanguage': 'English'}
{'BookName': 'BookH', 'BookID': '21221', 'BookLocation': 'C556', 'BookAuthor': 'Mark Lutz', 'BookLanguage': 'English'}
{'BookName': 'BookK', 'BookID': '55521', 'BookLocation': 'C776', 'BookAuthor': 'AuthorMissing', 'BookLanguage': 'English'}
{'BookName': 'BookL', 'BookID': '55521', 'BookLocation': 'C776', 'BookAuthor': 'Mark Lutz', 'BookLanguage': 'LanguageMissing'}

我需要在这里循环,匹配 BookID,存储信息(如果存在),然后以某种方式填写。

# create a new file
with open('output.csv', 'w') as outcsv:
    fieldnames = header
    writer = csv.DictWriter(outcsv, fieldnames=fieldnames, delimiter=',', lineterminator='\n')
    writer.writeheader()
    for row in sortedbyid:
        write.writerow(row)

【问题讨论】:

  • 能保证没有矛盾的数据吗? (例如,两本书具有相同的 ID 和不同的作者或语言?)
  • 是的!如果 BookID 相同,则作者和语言相同!
  • 我刚刚意识到我需要处理一个错误 - 如果只有一本书,请将其附加到文件末尾并使用相同的值。

标签: python python-3.x csv


【解决方案1】:

您可以遍历书籍列表,找到具有“AuthorMissing”的书籍,然后为每本书找到具有相同 ID 但具有实际作者的书籍:

for book in sortedbyid:
    if book['BookAuthor']=='AuthorMissing':
        matches = [ otherbook for otherbook in sortedbyid if book['BookID'] == otherbook['BookID'] and otherbook['BookAuthor'] != 'AuthorMissing' ]
        # Assuming no more than one match
        if len(matches)>0:
            book['BookAuthor'] = matches[0]['BookAuthor']

语言领域也可以这样做。

for book in sortedbyid:
    if book['BookLanguage']=='LanguageMissing':
        matches = [ otherbook for otherbook in sortedbyid if book['BookID'] == otherbook['BookID'] and otherbook['BookLanguage'] != 'LanguageMissing' ]
        # Assuming no more than one match
        if len(matches)>0:
            book['BookLanguage'] = matches[0]['BookLanguage']

当然,您可以将两者组合在一个循环中。

【讨论】:

  • 谢谢!!如果值为 None 或一些随机字符怎么办?
  • 如果是None,你可以在if语句中添加一个检查,例如if book['BookAuthor'] is None。至于随机字符,您需要定义真正的作者姓名与随机字符的资格。字符串“AAA AAA”可能看起来像随机字符,但就您的数据而言,它是有效的作者姓名!
猜你喜欢
  • 1970-01-01
  • 2013-06-18
  • 2018-03-16
  • 2020-05-29
  • 2021-05-12
  • 2016-07-15
  • 2013-04-22
  • 2016-02-24
  • 2020-07-30
相关资源
最近更新 更多