使用python解析CSV文件(稍后生成决策树)

使用python解析CSV文件(稍后生成决策树),python,csv,decision-tree,Python,Csv,Decision Tree,首先,完全披露:这是一个uni分配,所以我不想收到代码。:)。我更喜欢寻找方法;我对python非常陌生,读过一本书,但还没有写过任何代码 整个任务是导入CSV文件的内容,从CSV文件的内容创建决策树(使用),然后解析第二个CSV文件以针对该树运行。有一个很大的(可以理解的)偏好是让它能够处理不同的CSV文件(我问是否允许我们硬编码列名,主要是为了消除这种可能性,答案是否定的) CSV文件采用相当标准的格式;标题行用#标记,然后显示列名,其后的每一行都是一系列简单的值。例如: # Column1

首先,完全披露:这是一个uni分配,所以我不想收到代码。:)。我更喜欢寻找方法;我对python非常陌生,读过一本书,但还没有写过任何代码

整个任务是导入CSV文件的内容,从CSV文件的内容创建决策树(使用),然后解析第二个CSV文件以针对该树运行。有一个很大的(可以理解的)偏好是让它能够处理不同的CSV文件(我问是否允许我们硬编码列名,主要是为了消除这种可能性,答案是否定的)

CSV文件采用相当标准的格式;标题行用#标记,然后显示列名,其后的每一行都是一系列简单的值。例如:

# Column1, Column2, Column3, Column4
Value01, Value02, Value03, Value04
Value11, Value12, Value13, Value14
目前,我正在尝试解决第一部分:解析CSV。要为决策树做出决策,字典结构似乎是最符合逻辑的;所以我想做一些类似的事情:

Read in each line, character by character
If the character is not a comma or a space
    Append character to temporary string
If the character is a comma
    Append the temporary string to a list
    Empty string
Once a line has been read
    Create a dictionary using the header row as the key (somehow!)
    Append that dictionary to a list
但是,如果我这样做,我不知道如何在键和值之间进行映射。我还想知道是否有某种方法可以对列表中的每一本词典执行操作,因为我需要做的事情的效果是“每个人都返回列Column1和Column4的值,这样我就可以计算出谁拥有什么!”——我假设有某种机制,但我不知道怎么做


字典是最好的方法吗?使用其他数据结构做事情会更好吗?如果是,什么?

看看内置的。虽然你可能不能只用它,但你可以偷偷看一下代码


如果这是否定的,那么您的(伪)代码看起来非常好,尽管您应该使用
str.split()
函数并使用它,逐行读取文件。

Python内置了一些非常强大的语言构造。您可以从以下文件中读取行:

with open(name_of_file,"r") as file: for line in file: # process the line 要迭代列表或字典的内容,只需使用for循环,如下所示:

for val in mylist: # do something with val for key in mydict: # do something with key or with mydict[key] 对于mylist中的val: #对瓦尔做点什么 对于mydict中的密钥: #用key或mydict[key]做某事 由于在许多情况下,在对列表进行迭代时必须同时具有值和索引,因此还有一个名为enumerate的内置函数,可以省去您自己计算索引的麻烦:

for idx, val in enumerate(mylist): # do something with val or with idx. Note that val=mylist[idx] 对于idx,枚举中的val(mylist): #用val或idx做些什么。请注意,val=mylist[idx] 上述代码在功能上与以下代码相同:

idx=0 for val in mylist: # process val, idx idx += 1 idx=0 对于mylist中的val: #进程val,idx idx+=1 如果您这样选择,还可以迭代索引:

for idx in xrange(len(mylist)): # Do something with idx and possibly mylist[idx] 对于X范围内的idx(len(mylist)): #用idx做点什么,可能还有mylist[idx] 此外,您还可以使用获取列表中的元素数或字典中的键数

可以通过使用列表理解对字典或列表的每个元素执行操作;但是,我建议您只使用for循环来完成该任务。但是,举个例子:

>>> list1 = range(10) >>> list1 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> list2 = [2*x for x in list1] >>> list2 [0, 2, 4, 6, 8, 10, 12, 14, 16, 18] >>>列表1=范围(10) >>>清单1 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>>列表2=[2*x表示列表1中的x] >>>清单2 [0, 2, 4, 6, 8, 10, 12, 14, 16, 18] 如果您有时间,我建议您阅读CSV以获得更深入的知识。

正确解析CSV 我会避免使用str.split()解析字段,因为str.split()不会识别带引号的值。许多真实世界的CSV文件使用引号。

使用引用值的示例记录:

1997,Ford,E350,"Super, luxurious truck"
如果您使用str.split(),您将得到一条包含5个字段的记录:

('1997', 'Ford', 'E350', '"Super', ' luxurious truck"')
但您真正想要的是这样的记录,其中包含4个字段:

('1997', 'Ford', 'E350', 'Super, luxurious truck')
此外,除了数据中的逗号外,还可能需要处理数据中的换行符“\r\n”或“\n”。例如:

if key in mydict: print "Present" else: print "Absent"
1997,Ford,E350,"Super
luxurious truck"
1997,Ford,E250,"Ok? Truck"
因此,请小心使用:

file = open('filename.csv', 'r')
for line in file:
    # problem here, "line" may contain partial data
另外,正如John提到的,CSV标准是,在引号中,如果您得到一个双引号,那么它将变成一个引号

1997,Ford,E350,"Super ""luxurious"" truck"

('1997', 'Ford', 'E350', 'Super "luxurious" truck')
因此,我建议修改您的有限状态机,如下所示:

record[header[column_index]] += character
  • 一次解析每个字符。
  • 检查是否为报价,然后将状态设置为“in quote”
  • 如果是“in quote”,则存储当前字段中的所有字符,直到出现另一个quote。
  • 如果“在引号中”,并且还有另一个引号,请将引号字符存储在字段数据中。(不是结尾,因为空白字段不应该是'data',data',而是'data',data`)
  • 如果不是“在引号中”,则存储字符,直到找到逗号或换行符。
  • 如果是逗号,则保存字段并开始一个新字段。
  • 如果是换行、保存字段、保存记录,则启动新记录和新字段。
另一方面,有趣的是,我从未见过在CSV中使用#注释标题。因此,对我来说,这意味着您可能也必须在数据中查找注释行。使用#注释CSV文件中的一行不是标准

使用标题键将找到的字段添加到记录字典中 根据内存需求,如果CSV足够小(可能是10k到100k条记录),使用字典就可以了。只需存储所有列名的
列表
,就可以按索引(或编号)访问列名。然后在有限状态机中,找到逗号时增加列索引,找到换行符时重置为0

因此,如果您的头是
header=['Column1','Column2']
,那么当您找到一个数据字符时,可以这样添加它:

record[header[column_index]] += character

我对@Kaloyan Todorov提到的内置csv模块了解不多,但是,如果您正在阅读逗号分隔的行,那么您可以很容易地做到这一点:

for line in file:
    columns = line.split(',')
    for column in columns:
        print column.strip()

这将打印每行的所有条目,而不使用前导a和尾随空格。

简短回答:不要浪费时间和精力(1)重新实现内置csv模块(2)读取csv模块的源代码(它是用C编写的)只需使用i即可
import csv
reader = csv.reader(open("some.csv", "rb"))
for row in reader:
    print row
database.append(row)
import csv
reader = csvDictReader(open('my_file.csv','rb') # 'rb' = read binary
for d in reader:
    print d # this will print out a dictionary with keys equal to the first row of the file.