23

我的问题是处理大型 CSV 文件中的数据。

我正在寻找基于在该列中找到的值来确定(即猜测)该列的数据类型的最有效方法。我可能正在处理非常混乱的数据。因此,该算法应该具有一定的容错性。

这是一个例子:

arr1 = ['0.83', '-0.26', '-', '0.23', '11.23']               # ==> recognize as float
arr2 = ['1', '11', '-1345.67', '0', '22']                    # ==> regognize as int
arr3 = ['2/7/1985', 'Jul 03 1985, 00:00:00', '', '4/3/2011'] # ==> recognize as date
arr4 = ['Dog', 'Cat', '0.13', 'Mouse']                       # ==> recognize as str

底线:我正在寻找一个 python 包或一种可以检测到两者的算法

  • CSV 文件的架构,甚至更好
  • 单个列的数据类型为数组

猜测当前表示为字符串的数据类型的方法也朝着类似的方向发展。不过,我担心性能,因为我可能要处理许多大型电子表格(数据来自哪里)

4

5 回答 5

17

您可能对这个 python 库感兴趣,它可以为您对 CSV 和 XLS 文件进行这种类型的猜测:

它很高兴地扩展到非常大的文件,从互联网上流式传输数据等。

还有一个更简单的包装库,其中包括一个名为 dataconverters 的命令行工具:http://okfnlabs.org/dataconverters/ 和一个在线服务:https ://github.com/okfn/dataproxy !)

进行类型猜测的核心算法在这里:https ://github.com/okfn/messytables/blob/7e4f12abef257a4d70a8020e0d024df6fbb02976/messytables/types.py#L164

于 2013-08-03T20:15:22.330 回答
6

经过一番思考,这就是我自己设计算法的方式:

  • 出于性能原因:为每列取样(例如,1%)
  • 为样本中的每个单元格运行正则表达式匹配,检查数据类型
  • 根据频率分布为列选择适当的数据类型

出现的两个问题:

  • 什么是足够的样本量?对于小数据集?对于大型数据集?
  • 根据频率分布选择数据类型的足够高的阈值是多少?
于 2011-07-26T18:16:00.663 回答
3

您可以尝试使用正则表达式进行预解析。例如:

import re
pattern = re.compile(r'^-?\d+.{1}\d+$')
data = '123.42'
print pattern.match(data) # ----> object
data2 = 'NOT123.42GONNA31.4HAPPEN'
print pattern.match(data2) # ----> None

这样你就可以做一个正则表达式字典并尝试它们中的每一个,直到你找到一个匹配

myregex = {int: r'^-?\d+$', float: r'^\d+.{1}\d+$', ....}

for key, reg in myregex.items():
    to_del = []
    for index, data in enumerate(arr1):
        if re.match(reg,data):
            d = key(data) # You will need to insert data differently depending on function
            ....#---> do something 
            to_del.append(data) # ---> delete this when you can from arr1

不要忘记开头的 '^' 和结尾的 '$',否则,正则表达式可以匹配字符串的一部分并返回一个对象。

希望这可以帮助 :)

于 2011-07-26T04:50:33.797 回答
3

也许csvsql在这里有用吗?不知道它的效率如何,但绝对可以完成从 csvs 生成 sql create table 语句的工作。

$ csvsql so_many_columns.csv  >> sql_create_table_with_char_types.txt
于 2018-08-07T18:04:04.427 回答
1

我在 c# 中解决了同样的问题。这就是我构建样本集的方式:
对于 CSV 中的每一列,我选择值最长的行以及值最短的行。
然后我用第一个 50 个非空行构建了一个数组。
所以我的样本至少有 0 行,最多有 50 行,它们覆盖了一列中的整个范围。
之后,我会尝试从最宽的定义解析到最窄的:

if (value is String) then thisType = String;

if (value is DateTime) then thisType is DateTime;

if (value is Decimal) then thisType 是 Decimal;

if (value is Integer) then thisType 是 Integer;

if (value is Boolean) then thisType 是 Boolean;

我在 C# 中使用TryParse,但我确信其他语言也有类似的方法可以使用。

于 2012-02-08T15:17:32.113 回答