5

首先,全面披露:这是一个单向作业,所以我不想收到代码。:)。我更在寻找方法;我对python陌生,读过一本书但还没有写任何代码。

整个任务是导入 CSV 文件的内容,从 CSV 文件的内容创建决策树(使用ID3 算法),然后解析第二个 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 的值,所以我可以数数谁有什么!” - 我认为有一些机制,但我认为我不知道该怎么做。

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

4

7 回答 7

4

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

使用 open(name_of_file,"r") 作为文件:
    对于文件中的行:
         # 处理该行

您可以使用string.split函数沿逗号分隔行,并且可以使用string.strip消除中间空格。Python 有非常强大的列表字典

要创建一个列表,您只需使用 [] 之类的空括号,而要创建一个空字典,您可以使用 {}:

我的列表 = []; # 创建一个空列表
mydict = {}; # 创建一个空字典

您可以使用 .append() 函数插入到列表中,同时可以使用索引下标插入到字典中。例如,您可以使用mylist.append(5)将 5 添加到列表中,同时您可以使用mydict[key]=value将 keykey与 value关联起来value。要测试字典中是否存在键,可以使用in关键字。例如:

如果在 mydict 中键入:
   打印“礼物”
别的:
   打印“缺席”

要遍历列表或字典的内容,您可以简单地使用 for 循环,如下所示:

对于 mylist 中的 val:
    # 用 val 做一些事情

对于 mydict 中的键:
    # 用 key 或 mydict[key] 做一些事情

由于在许多情况下,在迭代列表时需要同时拥有值和索引,因此还有一个名为 enumerate 的内置函数可以省去您自己计算索引的麻烦:

对于枚举(mylist)中的 idx、val:
    # 用 val 或 idx 做一些事情。注意 val=mylist[idx]

上面的代码在功能上与:

idx=0
对于 mylist 中的 val:
   # 进程 val, idx
   idx += 1

如果您这样选择,您也可以遍历索引:

对于 xrange(len(mylist)) 中的 idx:
    # 用 idx 和 mylist[idx] 做一些事情

此外,您可以使用len获取列表中的元素数或字典中的键数。

可以通过使用列表推导对字典或列表的每个元素执行操作;但是,我建议您简单地使用 for 循环来完成该任务。但是,例如:

>>> 列表 1 = 范围(10)
>>> 列表1
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list2 = [2*x for x in list1]
>>> 列表2
[0、2、4、6、8、10、12、14、16、18]

如果你有时间,我建议你阅读Python 教程以获得更深入的知识。

于 2010-04-28T01:02:05.903 回答
4

使用docs.python.orgcsv中的模块的示例:

import csv
reader = csv.reader(open("some.csv", "rb"))
for row in reader:
    print row

print您可以将每一行保存到一个列表中,然后在 ID3 中处理它,而不是ing 行。

database.append(row)
于 2010-04-28T03:24:03.663 回答
2

简短的回答:不要浪费时间和精力 (1) 重新实现内置的 csv 模块 (2) 读取 csv 模块的源代码(它是用 C 编写的)——只要使用它!

于 2010-04-28T02:36:23.280 回答
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.
于 2010-04-28T10:08:35.293 回答
1

看看内置的CSV 模块。虽然您可能不能只使用它,但您可以先看看代码......

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

于 2010-04-28T01:00:02.497 回答
1

正确解析 CSV

我会避免使用 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')

所以我建议像这样修改你的有限状态机:

  • 一次解析每个字符。
  • 检查它是否是报价,然后将状态设置为“报价中”
  • 如果“in quote”,则将所有字符存储在当前字段中,直到有另一个引号。
  • 如果“in quote”,并且有另一个引号,则将引号字符存储在字段数据中。(不是结尾,因为空白字段不应该是 `data,"",data` 而是 `data,,data`)
  • 如果不是“引用”,则存储字符,直到找到逗号或换行符。
  • 如果是逗号,则保存字段并开始一个新字段。
  • 如果换行,保存字段,保存记录,开始一个新记录和一个新字段。

附带说明一下,有趣的是,我从未见过在 CSV 中使用 # 注释掉的标头。所以对我来说,这意味着您可能也必须在数据中查找注释行。使用 # 注释掉 CSV 文件中的一行是不标准的。

使用标题键将找到的字段添加到记录字典中

根据内存要求,如果 CSV 足够小(可能 10k 到 100k 条记录),则可以使用字典。只需存储list所有列名中的一个,以便您可以按索引(或编号)访问列名。然后在有限状态机中,找到逗号时增加列索引,找到换行符时重置为 0。

因此,如果您的标题是header = ['Column1', 'Column2'] Then 当您找到一个数据字符时,请像这样添加它:

record[header[column_index]] += character
于 2010-04-28T02:22:50.343 回答
0

我不太了解@Kaloyan Todorov 谈到的内置 csv 模块,但是,如果您正在阅读逗号分隔的行,那么您可以轻松地做到这一点:

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

这将打印每行的所有条目,而没有前导尾空格。

于 2010-04-28T02:28:46.883 回答