字典回顾
在Python中,字典是一个无序的、可变的数据类型,用于存储键(keys)和值(values)之间的映射关系。字典使用键来访问数据,与列表不同,不是使用索引来访问数据。
字典的主要特点包括:
字典由一系列键(keys)和值(values)组成,每个键映射一个值。
字典中的键必须是 不可变 对象,如字符串、数字、元组等,而值可以是任意对象。
字典是无序的,不支持索引,可以通过键查找值。
字典使用大括号{}来表示,每个键值对之间用逗号分隔。
字典是可变的,可以添加、删除、修改键值对。
字典长度可以使用内置的len()函数来计算,即键值对的个数。
字典操作
创建字典
1 2 3 4 5 my_dict = {} my_dict = {'name' : 'John' , 'age' : 25 , 'city' : 'New York' }
访问字典的值
1 2 my_dict['name' ] my_dict.getdefault('gender' ,'unknown' )
修改字典
1 2 my_dict['age' ] = 26 my_dict.update({'city' : 'San Francisco' })
删除字典
1 2 3 4 del my_dict['name' ] my_dict.pop('age' ) my_dict.clear() del my_dict
遍历字典
字典的遍历不保证顺序,如果需要有序地遍历字典,请使用内置库 collections 中的 OrderedDict 类型。
1 2 3 4 5 6 7 8 9 10 11 for key, value in my_dict.items(): print (key, value) for key in my_dict.keys(): print (key) for value in my_dict.values(): print (value)
鸢尾花分类问题
下载 iris_training.csv (1.0kB)
下载 iris_testing.csv (3.6kB)
原版代码(77行):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 import pandas as pd iris_type = ['Iris-setosa' ,'Iris-versicolor' ,'Iris-virginica' ] setosa_sum = [0 ,0 ,0 ,0 ,0 ] versicolor_sum = [0 ,0 ,0 ,0 ,0 ] virginica_sum = [0 ,0 ,0 ,0 ,0 ] se_len = 2 se_wid = 3 pe_len = 0 pe_wid = 1 amount = 4 trainData = pd.read_csv('iris_training.csv' )for index, row in trainData.iterrows(): if row.classification == 'Iris-setosa' : setosa_sum[se_len] += row.se_len setosa_sum[se_wid] += row.se_wid setosa_sum[pe_len] += row.pe_len setosa_sum[pe_wid] += row.pe_wid setosa_sum[amount] += 1 elif row.classification == 'Iris-versicolor' : versicolor_sum[se_len] += row.se_len versicolor_sum[se_wid] += row.se_wid versicolor_sum[pe_len] += row.pe_len versicolor_sum[pe_wid] += row.pe_wid versicolor_sum[amount] += 1 elif row.classification == 'Iris-virginica' : virginica_sum[se_len] += row.se_len virginica_sum[se_wid] += row.se_wid virginica_sum[pe_len] += row.pe_len virginica_sum[pe_wid] += row.pe_wid virginica_sum[amount] += 1 TestData = pd.read_csv('iris_testing.csv' )for index, row in TestData.iterrows(): distance = [] distance.append( (row.se_len - setosa_sum[se_len]/setosa_sum[amount]) ** 2 \ + (row.se_wid - setosa_sum[se_wid]/setosa_sum[amount]) ** 2 \ + (row.pe_len - setosa_sum[pe_len]/setosa_sum[amount]) ** 2 \ + (row.pe_wid - setosa_sum[pe_wid]/setosa_sum[amount]) ** 2 ) distance.append( (row.se_len - versicolor_sum[se_len]/versicolor_sum[amount]) ** 2 \ + (row.se_wid - versicolor_sum[se_wid]/versicolor_sum[amount]) ** 2 \ + (row.pe_len - versicolor_sum[pe_len]/versicolor_sum[amount]) ** 2 \ + (row.pe_wid - versicolor_sum[pe_wid]/versicolor_sum[amount]) ** 2 ) distance.append( (row.se_len - virginica_sum[se_len]/virginica_sum[amount]) ** 2 \ + (row.se_wid - virginica_sum[se_wid]/virginica_sum[amount]) ** 2 \ + (row.pe_len - virginica_sum[pe_len]/virginica_sum[amount]) ** 2 \ + (row.pe_wid - virginica_sum[pe_wid]/virginica_sum[amount]) ** 2 ) min_distance = min (distance) idx = distance.index(min_distance) print ('实际分类:' ,row.classification,'; 预测分类:' ,iris_type[idx])
修改版(50行):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 import pandas as pd iris_type = ['Iris-setosa' ,'Iris-versicolor' ,'Iris-virginica' ] iris_features = ["se_len" ,"se_wid" ,"pe_len" ,"pe_wid" ] sum_dict = {}for classification in iris_type: sum_dict[classification] = {} trainData = pd.read_csv('iris_training.csv' )for index, row in trainData.iterrows(): dict_class = sum_dict[row.classification] for feature in iris_features: dict_class[feature] = dict_class.setdefault(feature,0 )+row[feature] dict_class["amount" ] = dict_class.setdefault("amount" ,0 )+1 TestData = pd.read_csv('iris_testing.csv' )for index, row in TestData.iterrows(): distance = [] for classification in iris_type: distance.append( sum ( [row.se_len - sum_dict[classification][feature]/sum_dict[classification]["amount" ]**2 for feature in iris_features] ) ) min_distance = min (distance) idx = distance.index(min_distance) print ('实际分类:' ,row.classification,'; 预测分类:' ,iris_type[idx])
说明
作为一份合格的代码,应该有良好的可读性和可拓展性。
不像原版分别对每一种鸢尾花进行单独编码,对每一种属性单独写出语句,在修改版代码中使用两个列表分别储存了鸢尾花的种类和属性。如果要增加鸢尾花的种类,或增加鸢尾花的属性,修改版后的代码只需修改列表即可正常工作。
并且,可读性也有较大的提高。比起原版,修改版的核心代码更专注于逻辑:
训练阶段核心代码只有四行。
1 2 3 4 dict_class = sum_dict[row.classification]for feature in iris_features: dict_class[feature] = dict_class.setdefault(feature,0 )+row[feature] dict_class["amount" ] = dict_class.setdefault("amount" ,0 )+1
比起原版对每一个属性单独统计,这样的代码更为简洁,也有更佳的可读性。
预测阶段核心代码只有两行(为了可读性换行到七行):
1 2 3 4 5 6 7 for classification in iris_type: distance.append( sum ( [row.se_len - sum_dict[classification][feature]/sum_dict[classification]["amount" ]**2 for feature in iris_features] ) )
比起原版对每一种鸢尾花都写一段代码,我们通过循环,消灭了代码中的重复部分。并使用 sum 对列表推导式求和,实现了一行完成求出欧氏距离的平方的功能。