从两个 CSV 文件获取横截面

从两个 CSV 文件获取横截面

我有两个 CSV 文件正在处理。一个很大,大约有 200,000 行。另一个小得多,大约有 12,000 行。两者都符合相同的姓名和电子邮件地址格式(这里一切都是合法的,不用担心)。基本上,我试图通过删除较大文件中当前存在的所有值来仅获取第二个列表的子集。

因此,列表 A 有 ~200k 行,列表 B 有 ~12k 行。这些列表有一点重叠,如果列表 A 中也存在条目,我想从列表 B 中删除所有条目,只在列表 B 中保留新的唯一值。我有一些可以使用的工具。这台机器上装有 Open Office,还有 MySQL(查询没问题)。

创建具有数据交集的第三个 CSV 的最简单方法是什么?

答案1

从 Linux/Unix/Mac 命令行:

sort file1 file2 | uniq -d | sort file2 - | uniq -u

解释:

这将仅返回 file2 中与 file1 中的任何行不完全匹配的行。

脚步:

  1. sort file1 file2:将文件 1 和文件 2 连接在一起,对它们进行排序,然后将它们打印到标准输出。请注意,排序后,重复项将列在相邻行中(一行两次)。
  2. uniq -d:获取上一个命令的输出并打印仅显示重复的行
  3. sort file2 -:连接原始 file2 和上一个命令的输出(stdout,由文件名“ -”连字符表示),并将结果打印到 stdout。此外,file2 中任何也存在于 file1 中的项目都将在输出中重复(连续列出两次)。
  4. uniq -u:获取上一个命令的输出并仅打印不重复的项目(换句话说,仅打印未连续列出两次的项目)。

可能存在的陷阱:

假设 file1 中的任何给定行完全匹配file2 中有相应的行。例如,如果 file1 和 file2 有相同的电子邮件,但大小写不同;或者如果 file1 的名称为“Jon Sampson”,而 file2 有相同的电子邮件地址,名称为“Jonathan Sampson”,则它们不会被视为重复。

您可以通过预处理文件来控制这一点,删除除电子邮件地址之外的所有内容,并将电子邮件地址小写。在这种情况下,Unix 命令cut可能tr会有所帮助。或者,您可以切换到 SQL 以应对更复杂的情况。

文件大小:

一个 200,000 行的文件和一个 12,000 行的文件其实并不算大。我/usr/share/dict/words在 MacBook Pro 上使用该文件生成了类似大小的文件并测试了上述命令;运行时间不到 5 秒。

答案2

内特已经给了你一个很好的答案,但是从 Linux/Unix/Mac 命令行还有一个更短更长的方法:

join -t# -v2 <(sort file1.csv) <(sort file2.csv) > result.csv

注意事项:


  • 最初的问题是关于连接整行。我能想到的唯一消除join拆分需要的方法是将字段分隔符定义为任何文件中均未使用的字符(#在我的示例中)。我知道这很丑陋。

  • 输入文件必须按连接字段排序。您可以在一行中完成此操作(参见上文),但仅适用于bash。其他 shell 对此有不同的语法。

如果您的输入文件已排序:

join -t# -v2 file1.csv file2.csv > result.csv

对于 Windows,有一个本地连接端口

相关内容