【问题标题】:match names in csv file to filename in folder将 csv 文件中的名称与文件夹中的文件名匹配
【发布时间】:2016-09-21 14:41:19
【问题描述】:

我有一个 csv 文件中大约 7000 个名字的列表,按姓氏、姓名、出生日期等排列。我还有一个包含大约 7000 多个扫描文档(注册表格)的文件夹,其中每个文件的名称人作为文件名。

现在文件名可能与 csv 中的名称不完全匹配,即。 csv 中的 John Doe,文件名将是 John-Michael Doe 等。

我将如何编写一个程序来查看 csv 并查看扫描的文件夹中缺少哪些文件名?

我是一个完全的编程新手,任何建议都值得赞赏。

【问题讨论】:

  • 查看此问题的一种方法是制作两组,一组从 csv 中提取(姓名,姓氏),另一组从文件名中提取(通过拆分等)。除非你有一个一致的命名约定,否则你不会有一个完整的匹配,但这应该会让你的头痛减轻:)
  • 作为一个完全的编程新手,你可能会发现这个教程很有用:dataquest.io 你需要做一些事情,比如读取文件夹中的文件名,识别正则表达式,考虑“bigO”策略用于根据列表检查列表等。把它分解成小部分,继续破解它,祝你好运!

标签: python


【解决方案1】:

您要做的第一件事是将 CSV 读入内存。您可以使用csv module 执行此操作。最有用的工具是csv.DictReader,它将文件的第一行作为字典中的键,并读取其余部分:

import csv
with open('/path/to/yourfile.csv', 'r') as f:
    rows = list(csv.DictReader(f))

from pprint import pprint
pprint(rows[:100])

在 Windows 中,路径看起来会有所不同,类似于 c:/some folder/some other folder/(注意正斜杠而不是反斜杠)。

这将显示文件的前 100 行。例如,如果您有名为“First Name”、“Last Name”、“Date of Birth”的列,则如下所示:

[{'Date of Birth': 'Jan 1, 1970', 'First Name': 'John', 'Last Name': 'Doe'},
 {'Date of Birth': 'Jan 1, 1970', 'First Name': 'John', 'Last Name': 'Doe'},
 {'Date of Birth': 'Jan 1, 1970', 'First Name': 'John', 'Last Name': 'Doe'},
 {'Date of Birth': 'Jan 1, 1970', 'First Name': 'John', 'Last Name': 'Doe'},
 {'Date of Birth': 'Jan 1, 1970', 'First Name': 'John', 'Last Name': 'Doe'},
 {'Date of Birth': 'Jan 1, 1970', 'First Name': 'John', 'Last Name': 'Doe'},
 {'Date of Birth': 'Jan 1, 1970', 'First Name': 'John', 'Last Name': 'Doe'},
 {'Date of Birth': 'Jan 1, 1970', 'First Name': 'John', 'Last Name': 'Doe'},
 {'Date of Birth': 'Jan 1, 1970', 'First Name': 'John', 'Last Name': 'Doe'},
 {'Date of Birth': 'Jan 1, 1970', 'First Name': 'John', 'Last Name': 'Doe'}
 ...]

接下来,您要获取所有 7000 个文件的列表,使用 os.listdir

import os
images_directory = '/path/to/images/'
image_paths = [
    os.path.join(images_directory, filename)
    for filename in os.listdir(images_directory)]

现在您需要一些方法来从文件中提取名称。这主要取决于文件的结构方式。这个任务使用起来很棘手但非常强大的工具称为正则表达式,但可能一些简单的东西就足够了。例如,如果文件命名为“first-name last-name.pdf”,您可以编写一个简单的解析方法,如:

def parse_filename(filename):
    name, extension = filename.split('.')
    first_name, last_name = name.split(' ')
    return first_name.replace('-', ' '), last_name.replace('-', ' ')

确切的实现将取决于文件的命名方式,但让您入门的关键是str.splitstr.strip 和同一类中的其他一些。你也可以看看re module for handling regular expressions。正如我所说,这是一种更先进/更强大的技术,所以现在可能不值得担心。

进行匹配的简单算法如下所示:

name_to_filename = {parse_filename(filename.lower()): filename for filename in filenames}
matched_rows = []
unmatched_files = []
for row in rows:
    name_key = (row['First Name'].lower(), row['Last Name'].lower())
    matching_file = name_to_filename.get(name_key)  # This sees if we have a matching file name, and returns
                                                    # None otherwise.
    new_row = row.copy()
    if matching_file:
        new_row['File'] = matching_file
        print('Matched "%s" to %s' % (' '.join(name_key), matching_file))
    else:
        new_row['File'] = ''
        print('No match for "%s"' % (' '.join(name_key)))
    matched_rows.append(new_row)
with open('/path/to/output.csv', 'w') as f:
    writer = csv.DictWriter(f, ['First Name', 'Last Name', 'Date of Birth', 'File])
    writer.writeheader()
    writer.writerows(matched_rows)

这应该会为您提供一个输出电子表格,其中包含您可以匹配的任何行自动匹配,其余的为空白。根据您的数据的清洁程度,您也许可以手动匹配剩余的几个条目。只有 7000 个,“愚蠢的”启发式可能会抓住其中的大部分。如果您需要更高级的启发式算法,您可以查看名称中“单词”的Jaccard similarity,以及用于近似字符串匹配的difflib 模块。

当然,大部分代码完全无法解决您的问题,但希望它足以让您开始。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-24
    • 1970-01-01
    • 2017-04-16
    • 2020-04-30
    • 2022-08-17
    • 1970-01-01
    • 2016-11-06
    相关资源
    最近更新 更多