Python "输入数据
我有一个以 *.data 结尾的文件,这个文件里的数据是按照特定顺序排列的:
2.5,10,U1
3,4.5,U1
3,9,U1
3.5,5.5,U1
3.5,8,U1
4,7.5,U1
4.5,3.5,U1
4.5,4.5,U1
4.5,6,U1
5,5,U1
5,7,U1
7,6.5,U1
3.5,9.5,U2
3.5,10.5,U2
4.5,8,U2
4.5,10.5,U2
5,9,U2
5.5,5.5,U2
5.5,7.5,U2
在这些数据中(我有不同类型的数据,这里只是举个例子,只有两个类别),有两个类别:U1 和 U2,每个类别都有两个值……我需要做的是读取这些数据,并把它们分成不同的类别,在这个例子中就是 U1 和 U2……然后,我需要从每个类别中取出 2/3 的数据放到一个新的值(学习集 learning_set)里,剩下的 1/3 放到另一个值(测试集 test_set)里。
我开始写了这个代码:
data = open('set.data', 'rt')
data_list=[]
border=2./3
data_list = [line.strip().split(',') for line in data]
learning_set=data_list[:int(round(len(data_list)*border))]
test_set=data_list[int(round(len(data_list)*border)):]
但是这样我取出的 2/3 和 1/3 是从所有数据中分的,而不是从每个类别中分的。
非常感谢大家的帮助!
5 个回答
2
我觉得这段内容还是有点用的(而且我已经打出来了),我会用类似下面的方式来实现...
from itertools import groupby
from operator import attrgetter
from collections import namedtuple
row_container = namedtuple('row', 'val1,val2,klass')
def process_row(row):
"""Return a named tuple"""
return row_container(float(row[0]), float(row[1]), row[2])
def bisect_list(split_list, fraction):
split_index = int(fraction * len(split_list))
return split_list[:split_index], split_list[split_index:]
data = open('test.csv', 'rt')
## Parse & process each line
data = (row.strip().split(',') for row in data)
data = (process_row(row) for row in data)
## Sort & group the data by class
sorted_data = sorted(data, key=attrgetter('klass'))
grouped_data = groupby(sorted_data, attrgetter('klass'))
## For each class, create learning and test sets
final_data = {}
for klass, class_rows in grouped_data:
learning_set, test_set = bisect_list(list(class_rows), 0.66)
final_data[klass] = dict(learning=learning_set, test=test_set)
这个方法的操作方式和之前其他的回答差不多。它使用了命名元组。bisectlist()
是从 @senderle 那里借来的。
2
哦,你想要了解一下itertools.groupby
这个东西:
import itertools
class_dict = dict(itertools.groupby(data_list, key=lambda x: x[-1]))
class_names = class_dict.keys()
class_lists = [list(group) for group in class_dict.values()]
然后只需要根据需要切分每个在class_lists
里的列表,并用结果来扩展学习集和测试集。
这里有一个完整的解决方案:
data_list = [line.strip().split(',') for line in data]
data_list.sort(key=lambda x: x[-1])
def bisect_list(split_list, fraction):
split_index = int(fraction * len(split_list))
return split_list[:split_index], split_list[split_index:]
learning_set, test_set = [], []
for key, group in itertools.groupby(data_list, key=lambda x: x[-1]):
l, t = bisect_list(list(group), 0.66)
learning_set.extend(l)
test_set.extend(t)
2
你可以在读取数据后,把你的列表分成两个不同的子集:
data_list_1 = [(x,y,c) for (x,y,c) in data_list if c=='U1']
data_list_2 = [(x,y,c) for (x,y,c) in data_list if c=='U2']
然后,你可以像之前一样,基于这些过滤后的列表,构建两个不同的学习集和测试集,比如:
learning_set = data_list_1[:int(round(len(data_list_1)*border))] + data_list_2[:int(round(len(data_list_2)*border))]
测试集也是同样的处理。
更新:如果你事先不知道有哪些类别,可以使用以下代码先检测所有的类别,然后再对它们进行循环处理。
classes = set([t[-1] for t in data_list])
learning_set = []
test_set = []
for cl in classes:
data_list_filtered = [t for t in data_list if t[-1]==cl]
learning_set += data_list_filtered[:int(round(len(data_list_filtered)*border))]
test_set += data_list_filtered[int(round(len(data_list_filtered)*border)):]