python - 如何使用 DictReader 和 DictWriter 只写字段的子集

标签 python csv

名为 Sample.csv 的 CSV 测试文件包含:

Brand, Price, Weight, Type
brand1, 6.05, 3.2, orange
brand2, 8.05, 5.2, orange
brand3, 6.54, 4.2, orange
brand1, 6.05, 3.2, pear
brand2, 7.05, 3.6, pear
brand3, 7.45, 3.9, pear
brand1, 5.45, 2.7, apple
brand2, 6.05, 3.2, apple
brand3, 6.43, 3.5, apple
brand4, 7.05, 3.9, apple
brand1, 8.05, 4.2, plum
brand2, 3.05, 2.2, plum

我的代码是:

import csv
headers = ['Brand','Price','Type']

with open('sample.csv', newline='') as rf:
    reader = csv.DictReader(rf, delimiter=',',fieldnames=headers)
    with open('output.csv', 'w', newline='') as wf:
        writer = csv.DictWriter(wf, delimiter=',', extrasaction='ignore', fieldnames=headers)
        writer.writerow(dict((fn,fn) for fn in writer.fieldnames))
        for row in reader:
           print(row)
           writer.writerow(row)

我只是想在输出文件中获取品牌、价格和类型,但我得到了:

Brand,Price,Type
Brand, Price, Weight
brand1, 6.05, 3.2
brand2, 8.05, 5.2
brand3, 6.54, 4.2
brand1, 6.05, 3.2
brand2, 7.05, 3.6
brand3, 7.45, 3.9
brand1, 5.45, 2.7
brand2, 6.05, 3.2
brand3, 6.43, 3.5
brand4, 7.05, 3.9
brand1, 8.05, 4.2
brand2, 3.05, 2.2

为什么我在输出中得到的是 Weight 字段,而不是 Type 字段?

请注意,为调试添加了 writer.writerow(dict((fn,fn) for fn in writer.fieldnames)) 行,故意打印出标题两次。

最佳答案

您在 headers 中输入列名 Brand, Price, Weight 的事实不会使 DictReader 解析并仅返回这些列从源文件。它只会将它在文件中找到的列分配给这些键 - 实际上,您可以将它们命名为 First、Second、Third,结果将是相同的。

你有两个选择:

使用源标题行

利用你有标题行的事实,让 DictReader 根据它命名键,然后只写你想要的:

import csv
headers = ['Brand', 'Price', 'Type']

with open('sample.csv') as rf:
    reader = csv.DictReader(rf, delimiter=',', skipinitialspace=True)
    with open('output.csv', 'w') as wf:
        writer = csv.DictWriter(wf, delimiter=',', extrasaction='ignore', fieldnames=headers)
        writer.writeheader()
        for row in reader:
            print(row)
            writer.writerow(row)

明确设置列(在源和输出中)

明确源中的列是什么,并明确输出中的内容 - 使用两个列表:

import csv
present_headers = ['Brand', 'Price', 'Weight', 'Type']
desired_headers = ['Brand', 'Price', 'Type']

with open('sample.csv') as rf:
    reader = csv.DictReader(rf, delimiter=',', fieldnames=present_headers, skipinitialspace=True)
    with open('output.csv', 'w') as wf:
        writer = csv.DictWriter(wf, delimiter=', ', extrasaction='ignore', fieldnames=desired_headers)
        writer.writeheader()
        next(reader, None)   #to skip writing the header row from the source
        for row in reader:
            # print(row)
            writer.writerow(row)

鉴于您问题中的示例,两个选项都会产生相同的结果。

一些评论 - 问题中的示例在标题和数据行中都有分隔符 , 后跟空格。如果它确实存在(不是复制和粘贴错误),阅读器中的选项 skipinitialspace=True 将删除它 - 否则它会成为列中数据的一部分。

另一个是不需要手动构造 DictWriter 的标题行 - 这就是 writerheader() 方法的用途。

最后,您可以在选项 2 中看到在写入数据之前调用 next(reader, None) - 它的目的是让读取器产生第一行,就像现在一样一个普通的(不是标题),我们不想在输出中复制它。

关于python - 如何使用 DictReader 和 DictWriter 只写字段的子集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43697024/

相关文章:

mysql - 如何格式化 CSV 文件以导入多个 MySQL 表

C# csv文件到数组

python - 如何将 pendulum 转换为 datetime.datetime 类型?

python - 打包 Python 库

java - 使用 csv 文件中的数据打印数字

csv - 是否可以在 csv 中包含列名,并在 Snowflake 中将其复制到语句中?

json - 当 csv 太大时,CSV 到 JSON npm 包失败

python - 什么是__pycache__?

Python:在 tarfile 中使用过滤器

python - MLP(ReLu) 在几次迭代后停止学习。 tensorflow