自动检测文件中CSV标题的存在

问题描述 投票:19回答:6

简短问题:如何自动检测CSV文件是否在第一行中包含标题?

详细信息:我编写了一个小型CSV解析引擎,将数据放入一个我可以作为(大约)内存数据库访问的对象。编写原始代码是为了解析具有可预测格式的第三方CSV,但我希望能够更普遍地使用此代码。

我正在尝试找出一种可靠的方法来自动检测CSV标头的存在,因此脚本可以决定是使用CSV文件的第一行作为键/列名还是立即开始解析数据。由于我只需要一个布尔测试,我可以在自己检查CSV文件之后轻松指定一个参数,但我宁愿不必去(自动化)。

我想我必须解析前3个? CSV文件的行,并查找某种类型的模式以与标头进行比较。我正在做三个特别糟糕的噩梦,其中:

  1. 由于某种原因,标题包括数字数据
  2. 前几行(或CSV的大部分)为空
  3. 标题和数据看起来太相似,无法区分它们

如果我可以获得“最佳猜测”并让解析器失败并出现错误,或者如果无法确定则发出警告,那就没问题。如果在时间或计算方面这将是非常昂贵的事情(花费的时间超过它应该拯救我的时间),我会高兴地废弃这个想法,然后回到“重要的事情”。

我正在使用PHP,但这让我更像是一个算法/计算问题而不是特定于实现的问题。如果有一个我可以使用的简单算法,那很好。如果你能指出一些相关的理论/讨论,那也很棒。如果有一个巨型库可以进行自然语言处理或300种不同的解析,我对此并不感兴趣。

php algorithm csv automation
6个回答
15
投票

正如其他人所指出的那样,你不能以100%的可靠性做到这一点。在某些情况下,“大部分正确”是有用的,但是 - 例如,具有CSV导入功能的电子表格工具通常会尝试自行解决这个问题。这里有一些启发式指示第一行不是标题:

  • 第一行的列不是字符串或为空
  • 第一行的列并非都是唯一的
  • 第一行似乎包含日期或其他常见数据格式(例如,xx-xx-xx)

6
投票

从最普遍的意义上讲,这是不可能的。这是一个有效的csv文件: 名称 吉姆 汤姆 法案

大多数csv读者只需将hasHeader作为选项,并允许您根据需要传入自己的标题。即使在您认为可以检测到的情况下,即字符标题和数字数据,您也可能遇到灾难性故障。如果您的专栏是宝马系列列表怎么办? 中号 3 五 7

您将错误地处理此问题。最糟糕的是,你将失去最好的车!


3
投票

在纯粹抽象的意义上,我不认为你的问题有一个万无一失的算法答案,因为它归结为:“如果我对它们中的任何一个一无所知,我如何区分dataA和dataB?”。 dataA总是有可能与dataB无法区分。也就是说,我会从简单开始,只根据需要增加复杂性。例如,如果检查前五行,对于给定的列(或列),如果行2-5中的数据类型全部相同但与第1行中的数据类型不同,则很可能存在标题行(增加样本量可减少出错的可能性)。这将(sorta)解决#1 /#3 - 如果所有行都被填充但是数据无法区分以允许调用程序决定下一步该做什么,则可能抛出异常。对于#2,简单地不要将行计为一行,除非并且直到它拉出非空数据....除了空文件之外的所有数据(在这种情况下你会点击EOF)。它永远不会是万无一失的,但它可能“足够接近”。


1
投票

这实际上取决于您希望工具的“一般”程度。如果数据总是数字的,只要你假设非数字标题(这似乎是一个非常公平的假设),你就可以轻松实现。

但除此之外,如果您还不知道数据中存在哪些模式,那么您无法提前测试它们。

FWIW,我实际上只是编写了一个脚本来解析TSV中的一些东西,所有这些都来自同一个源码。源代码的标题/格式是如此分散,以至于只需让脚本在执行时从命令行向我询问问题。 (这是一个标题吗?哪些列很重要?)。所以没有自动化,但它让我飞过我正在处理的数据集,而不是试图预测每个有趣的格式化案例。此外,我的答案保存在一个文件中,所以我只需要每个文件一次。不理想,但效率很高。


1
投票

本文提供了一些很好的指导:

基本上,您可以根据第一行是否包含字符串以及其余行数等来对列进行统计分析。

http://penndsg.com/blog/detect-headers/


0
投票

如果你有一个像这样的标题。

ID,姓名,电子邮件,日期1,john,john @ john.com,2020年1月12日

然后在标题行上执行filter_var(str,FILTER_VALIDATE_EMAIL)将失败。由于电子邮件地址仅在行数据中。因此,请检查标题行中的电子邮件地址(假设您的CSV中包含电子邮件地址)。

第二个想法。 http://php.net/manual/en/function.is-numeric.php检查is_numeric的标题行,很可能标题行中没有数字数据。但很可能数据行会有数字数据。

如果您知道列中有日期,那么检查标题行的日期也会有效。

显然,您需要预期的数据类型。我正在“期待”电子邮件地址。

© www.soinside.com 2019 - 2024. All rights reserved.