根据 CSV 文件行中的值确定数据类型

Posted

技术标签:

【中文标题】根据 CSV 文件行中的值确定数据类型【英文标题】:Determining Data Type From Value in Row of CSV File 【发布时间】:2016-11-21 07:48:02 【问题描述】:

我编写了一个 Python 程序,它读取 CSV 文件并将它们作为 mysql 的插入语句输出。现在我想要一个能够使用列标题为每个新表形成CREATE 语句的附加程序。由于 MySQL 格式,我需要能够确定列中每个值的类型,类似于 shell 中的 type() 函数。我的想法是在列标题之后读取 CSV 文件的第二行,并提取由 , 分隔的值(即每列中的一个值)。然后获取该值并通过type() 函数运行它并返回int, str, float, etc.。稍后我将使用type() 返回的值执行一些if statements,以将正确的数据类型附加到CREATE 语句的列标题的末尾。

到目前为止,我已经设法将每个值从第一行的编译列表中提取出来并打印出它的 type()。唯一的问题是列表中的所有内容都被视为字符串,因此唯一的返回是<class 'str'>。如果我知道它是什么类型的值,我将能够从字符串转换为正确的类型,但这违背了程序的整个目的。我确信有一种更好的方法可以做到这一点,它不会将第一行作为字符串列表吐出,但我不知道该怎么做。以下是我目前所拥有的以及如何继续的想法:

import csv, os

path = 'C:/Users/user/Desktop/file/test/'
for file in os.listdir(path):
    if file.endswith('.csv'):
        with open(path +file) as inFile:
            with open(path + file[:-4] + ".txt", "w") as outFile:
                csvFile = csv.reader(inFile)
                columnHeader = next(csvFile)
                firstRow = next(csvFile)
                i = 0
                for value in firstRow:
                    valueType = (type(value))
                    for header in columnHeader:
                        if valueType = class 'str': # Don't think this formatting is correct
                            columnHeader.append(' varchar (255)')
                        if valueType = class 'int':
                            columnHeader.append(' int')
                        if valueType = class 'float':
                            columnHeader.append(' float')

我也研究过使用 this 库,但更愿意自己做。

我选择的方法是否合理/可行?你能想到什么更好的方法来做到这一点吗?如果有,怎么做?

【问题讨论】:

好久没看到好问题了。谢谢!!我想到了两件事:*一系列 try-except 块 (try: int(x), except: try: float(x), except str(x)) 或使用 eval 的东西,这将非常优雅。 @MarcB 这正是我上面所说的。这些 CSV 文件中包含大量数据,因此手动执行此操作是不合理的。 【参考方案1】:

这是简单的方法:

def find_type(a):
    try:
        var_type = type(int(a))
    except ValueError:
        try:
            var_type = type(float(a))
        except ValueError:
            var_type = type(a)
    return var_type

a = ['123123', '11.21', 'Some Bank', '11/2/1995']

print([find_type(x) for x in a])
#[<class 'int'>, <class 'float'>, <class 'str'>, <class 'str'>]

我很确定还有更优雅的方法。

【讨论】:

我什至不知道try: except: 函数,但这正是我想要的。现在我仍然需要尝试一下才能让它完全按照我想要的方式工作,但这肯定会让我开始。谢谢!【参考方案2】:

这是区分 float 和 int 并假设其他所有内容都是字符串的一种可能性。如果该值有小数点,则它会尝试将其转换为浮点数,如果没有则尝试将其转换为 int。如果任一转换失败,则将值保留为字符串。

if '.' in val:
    try:
        val = float(val)
    except ValueError:
        pass
else:
    try:
        val = int(val)
    except ValueError:
        pass

【讨论】:

这正是我一直在寻找的,只是我选择了@Ev。 Kounis 的回答是因为对我来说,同时运行多个 try:except: 语句而不是将它们放在另一个 if: else: 语句中更有意义。但是,我仍然感谢您花时间提供高质量的答案。谢谢! @ThoseKind 使用 if else 语句,如果在我的系统上快约 3 倍。无论您使用什么解决方案,排除try except 语句中的所有错误通常都是不好的做法;你应该指定ValueError,如果它不能进行类型转换,这是python引发的。 我意识到我的评论与我的预期不同。我指的是在指定的if: 循环中运行try: except: 语句可能会导致我出错,因为我不确定哪些值包含'.'。我确实同意这会起作用,并且通常可能是更好的做法,但在我的具体情况下,我并不完全确定这对每个值都有效。

以上是关于根据 CSV 文件行中的值确定数据类型的主要内容,如果未能解决你的问题,请参考以下文章

Python数据分析基础——读写CSV文件2

使用 python,我如何从 csv 中获取唯一行,但获取合并了哪些行(或行中的值)的记录?

遍历 CSV 以确定数据类型

从 CSV 确定数据类型 - Python

js中这样获取DataTable中的行中的列数据??

基于 1 列和另一组的值合并 2 个 csv 文件