首先,完全披露:这是单向分配,所以我不想接收代码。 :)。我更需要寻找方法;我已经非常是python的新手,读过一本书但还没有编写任何代码。
整个任务是导入CSV文件的内容,从CSV文件的内容创建决策树(使用ID3 algorithm),然后解析第二个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的值,所以我可以数谁有什么!“ - 我认为有一些机制,但我认为我不知道该怎么做。
字典是最好的方法吗?使用其他数据结构做事情会更好吗?如果是这样,是什么?
答案 0 :(得分:4)
Python内置了一些非常强大的语言结构。您可以从以下文件中读取行:
with open(name_of_file,"r") as file: for line in file: # process the line
您可以使用string.split函数分隔逗号中的行,您可以使用string.strip来消除插入的空格。 Python功能非常强大lists和dictionaries。
要创建列表,只需使用[]等空括号,而创建使用{}的空字典:
mylist = []; # Creates an empty list mydict = {}; # Creates an empty dictionary
您可以使用.append()函数插入列表,同时可以使用索引下标插入字典。例如,您可以使用mylist.append(5)
将5添加到列表中,同时可以使用mydict[key]=value
将密钥key
与值value
相关联。要测试字典中是否存在密钥,您可以使用in
关键字。例如:
if key in mydict: print "Present" else: print "Absent"
要遍历列表或字典的内容,您只需使用for循环,如下所示:
for val in mylist: # do something with val for key in mydict: # do something with key or with mydict[key]
因为在很多情况下,迭代列表时必须同时具有值和索引,所以还有一个名为enumerate的内置函数可以节省您自己计算索引的麻烦:
for idx, val in enumerate(mylist): # do something with val or with idx. Note that val=mylist[idx]
上面的代码功能相同:
idx=0 for val in mylist: # process val, idx idx += 1
如果您这样选择,也可以迭代索引:
for idx in xrange(len(mylist)): # Do something with idx and possibly mylist[idx]
此外,您可以使用len获取列表中的元素数量或字典中的键数。
可以通过使用列表理解对字典或列表的每个元素执行操作;但是,我建议您只使用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]
如果您有时间,我建议您阅读Python tutorial以获得更深入的知识。
答案 1 :(得分:4)
使用docs.python.org中的csv
模块的示例:
import csv
reader = csv.reader(open("some.csv", "rb"))
for row in reader:
print row
而不是print
行,您可以将每行保存到列表中,然后在ID3中处理它。
database.append(row)
答案 2 :(得分:2)
简短回答:不要浪费时间和精力(1)重新实现内置的csv模块(2)读取csv模块的源代码(用C语言编写) - 只是使用它!
答案 3 :(得分:2)
查看csv.DictReader。
示例:
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.
答案 4 :(得分:1)
查看内置CSV module。虽然你可能不能只使用它,但你可以偷看一下代码......
如果这是禁忌,你的(伪)代码看起来非常好,尽管你应该使用str.split()
函数并使用它,逐行读取文件。
答案 5 :(得分:1)
我会避免使用str.split()来解析字段,因为str.split()将无法识别引用的值。许多真实的CSV文件都使用引号。 http://en.wikipedia.org/wiki/Comma-separated_values
使用引用值的示例记录:
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”。例如:
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
另外,就像约翰提到的那样,CSV标准是,如果你得到一个双引号,那么在报价中,它会变成一个引用。
1997,Ford,E350,"Super ""luxurious"" truck"
('1997', 'Ford', 'E350', 'Super "luxurious" truck')
所以我建议像这样修改你的有限状态机:
另一方面,有趣的是,我从未在CSV中看到使用#注释掉的标题。所以对我来说,这意味着您可能还必须在数据中查找注释行。使用#注释掉CSV文件中的一行不是标准的。
根据内存要求,如果CSV足够小(可能是10k到100k记录),使用字典就可以了。只需存储所有列名的list
,以便按索引(或数字)访问列名。然后在有限状态机中,当找到逗号时递增列索引,并在找到换行符时重置为0.
因此,如果您的标题是header = ['Column1', 'Column2']
那么当您找到数据字符时,请按以下方式添加:
record[header[column_index]] += character
答案 6 :(得分:0)
我不太了解@Kaloyan Todorov谈到的内置csv模块,但是,如果你正在阅读逗号分隔的行,那么你可以很容易地做到这一点:
for line in file:
columns = line.split(',')
for column in columns:
print column.strip()
这将打印每一行的所有条目,而不会引出拖尾空格。