如何使输出 csv 文件的文件名等于列的内容

How do I make the filename of the output csv file equal to the the content of a column

我有一个巨大的 csv 文件,里面有我们所有的学生花名册。所以, 1) 我想根据 课程名。 2) 如果我可以让输出 csv 文件的名称等于 课程名称(例如:Algebra1.csv),这将使我的生活如此丰富 更好的。是否可以遍历 csv 文件的 courses_column,当课程名称更改时,它会为该课程创建一个新的 csv 文件。我想我可以读取字典的键 'read_rosters' 然后做一个 while 循环?

csv 输入文件的示例如下所示:

学生名字,学生姓氏,Class 教师,课程名称,初级学习中心

johnny, doe, smith, algebra1, 在线

jane, doe, austin, geometry, campus

这是我目前的情况:

import os
import csv

path = "/PATH/TO/FILE"

with open(os.path.join(path, "student_rosters.csv"), "rU") as rosters:
        read_rosters = csv.DictReader(rosters)
        for row in read_rosters:
            course_name = row['COURSES_COLUMN_HEADER']
            csv_file = os.path.join(course_name, ".csv")
            course_csv = csv.writer(open(csv_file, 'wb').next()

首先,这不是你想要的:

csv_file = os.path.join(course_name, ".csv")

它将在名为 course_name 的子目录中创建一个名为 .csv 的文件。你可能想要这样的东西:

csv_file = os.path.join(path, course_name + ".csv")

此外,以下有两个问题:(a) 不平衡的括号和 (b) writer 对象没有 next 方法:

course_csv = csv.writer(open(csv_file, 'wb').next()

试试看:

course_csv = csv.writer(open(csv_file, 'wb'))

然后,您需要将您选择的内容写入新文件,可能使用 writeheaderwriterowwriterows 方法:

course_csv.writeheader(something_of_your_choosing)
course_csv.writerow(something_else_of_your_choosing)

在您当前的代码中,您正在为您阅读的每一行打开一个输出 csv 文件。这会很慢,而且正如您目前所写的那样,它不会起作用。这是因为在打开文件时使用 "wb" 模式会删除文件中之前的所有内容。您可以使用 "a" 模式,但这仍然很慢。

如何最好地解决问题在一定程度上取决于您的数据。如果您可以依靠输入始终将具有相同课程的行彼此相邻,则可以使用 itertools 模块中的 groupby 轻松地将适当的行写在一起:

from itertools import groupby
from operator import itemgetter

with open(os.path.join(path, "student_rosters.csv"), "rb") as rosters:
    reader = csv.DictReader(rosters)
    for course, rows in groupby(reader, itemgetter('COURSES_COLUMN_HEADER')):
        with open(os.path.join(path, course + ".csv"), "wb") as outfile:
            writer = csv.DictWriter(outfile, reader.fieldnames)
            writer.writerows(rows)

如果您不能依赖行的组织,您有几个选择。一种方法是将所有行读入列表,然后按课程对它们进行排序,并像上面的代码一样使用 itertools.groupby

另一种选择是继续一次只读取一行,并将每个输出行放入适当的文件中。我建议保留一个作者对象的字典,按课程名称索引。这可能是这样的:

writers = {}
with open(os.path.join(path, "student_rosters.csv"), "rb") as rosters:
    reader = csv.DictReader(rosters)
    for row in reader:
        course = row['COURSES_COLUMN_HEADER']
        if course not in writers:
            outfile = open(os.path.join(path, course + ".csv"), "wb")
            writers[course] = csv.DictWriter(outfile, reader.fieldnames)
        writers[course].writerow(row)

如果您在生产中使用它,您可能希望添加一些代码以在完成文件后关闭它们,因为您不能使用 with 语句自动关闭它们。

在我上面的示例代码中,我已经让代码写出完整的行,就像它们在输入中一样。如果您不想这样,您可以将 DictWriter 的第二个参数更改为您要写入的列名序列。您还需要包含参数 extrasaction="ignore",以便在写入您想要的列时忽略行字典中的额外值。