频道栏目
读书频道 > 数据库 > 其他综合 > Python数据分析与挖掘实战
2.2.3 数据结构
2015-12-11 15:12:29     我来说两句
收藏   我要投稿

本文所属图书 > Python数据分析与挖掘实战

本书共15章,分两篇:基础篇和实战篇。基础篇介绍了数据挖掘的基本原理,实战篇介绍了一个个真实案例,通过对案例深入浅出的剖析,使读者在不知不觉中通过案例实践获得数据挖掘项目经验,同时快速领悟看似难懂的  立即去当当网订购

Python有4个内建的数据结构—List(列表)、Tuple(元组)、Dictionary(字典)以及Set(集合),它们可以统称为容器(container),因为它们实际上是一些“东西”组合而成的结构,而这些“东西”,可以是数字、字符甚至是列表,或者是它们之间几种的组合。通俗地讲,容器里是什么都行,而且容器里的元素类型不要求相同。

(1)列表/元组

列表和元组都是序列结构,它们本身很相似,但又有一点不同的地方。

从外形上看,列表与元组的区别是,列表是用方括号标记的,如a=[1, 2, 3],而元组是用圆括号标记的,如b=(4, 5, 6),访问列表和元组中的元素的方式都是一样的,如a[0]等于1,b[2]等于6等。上面已经谈及,容器里是什么都行,因此,下面的定义也是成立的。

c = [1, 'abc', [1, 2]]

'''
c是一个列表,列表的第一个元素是整型1,第二个是字符串'abc',第三个是列表[1, 2]

'''
从功能上看,列表与元组的区别是,列表可以被修改,而元组不可以。比如,对于a=[1, 2, 3],那么语句a[0]=0,就会将列表a修改为[0, 2, 3],而对于元组b=(4, 5, 6),语句b[0]=1就会报错。要注意的是,如果已经有了一个列表a,同时想复制a,命名为变量b,那么b=a是无效的,这时候b仅仅是a的别名(或者说引用),修改b也会修改a的。正确的复制方法应该是b=a[:]。

与列表有关的函数是list,与元组有关的函数是tuple,它们的用法和功能几乎一样,都是将某个对象转换为列表/元组,如list('ab')的结果是['a', 'b'],tuple([1, 2])的结果是(1, 2)。表2-1是一些常见的与列表/元组相关的函数。


 

此外,作为对象,列表本身自带了很多实用的方法(元组不允许修改,因此方法很少),见表2-2。



  
最后,不能不提的是“列表解析”这一功能,它能够简化我们对列表内元素逐一进行操作的代码,如下面的代码

a = [1, 2, 3]
b = []
for i in a:
  b.append(i + 2)
可以简化到
a = [1, 2, 3]
b = [i+2 for i in a]

这样的语法不仅方便,而且直观!充分体现了Python语法的人性化。在本书中,我们将会比较多地用到这样简洁的代码。

(2)字典

Python引入了“自编”这一方便的概念。从数学上来讲,它实际上是一个映射。通俗来讲,它也相当于一个列表,然而它的“下标”不再是以0开头的数字,而是让自己定义的“键”(Key)开始。

创建一个字典的基本方法为:

d = {'today':20, 'tomorrow':30}

这里的'today'、'tomorrow'就是字典的键,它在整个字典中必须是唯一的,而20、30就是键对应的值,访问字典中元素的方法也很直观。

d['today'] #该值为20

d['tomorrow'] #该值为30

还有其他一些比较方便的方法来创建一个字典,如通过dict()函数转换,或者通过dict.fromkeys来创建,如下。

dict([['today', 20], ['tomorrow', 30]]) #也相当于{'today':20, 'tomorrow':30}
dict.fromkeys(['today', 'tomorrow'], 20) #相当于{'today':20, 'tomorrow':20}

很多字典的函数和方法与列表是一样的,因此在这里就不再赘述了。

(3)集合

Python内置了集合这一数据结构,同数学上的集合概念基本上是一致的,它与列表的区别在于:1.它的元素是不重复的,而且是无序的;2.它不支持索引。一般我们通过花括号{}或者set()函数来创建一个集合。

s = {1, 2, 2, 3} #注意2会自动去重,得到{1, 2, 3}
s = set([1, 2, 2, 3]) #同样,它将列表转换为集合,得到{1, 2, 3}

由于集合的特殊性(特别是无序性),因此集合有一些特别的运算。

a = t | s #t和s的并集
b = t & s #t和s的交集 
c = t – s #求差集(项在t中,但不在s中) 
d = t ^ s #对称差集(项在t或s中,但不会同时出现在二者中)

在本书中,集合并不常用,所以这里仅仅简单地介绍它,并不进行详细说明,如果读者想深入了解集合对象,请自行搜索相关教程。

(4)函数式编程

函数式编程(Functional Programming)或者函数程序设计,又称泛函编程,是一种编程范型,它将计算机运算视为数学上的函数计算,并且避免使用程序状态以及易变对象。简单来讲,函数式编程是一种“广播式”的编程,一般结合前面提到过的lambda定义函数,用于科学计算中,会显得特别简洁方便。

在Python中,函数式编程主要由几个函数的使用构成:lambda()、map()、reduce()、filter(),lambda前面已经介绍过,主要用来自定义“行内函数”,所以现在我们逐一介绍后三个。

首先介绍map()函数。假设有一个列表a=[1, 2, 3],要给列表中的每个元素都加2得到一个新列表,利用前面已经谈及过的“列表解析”,我们可以这样写:

b = [i+2 for i in a]
而利用map函数我们可以这样写:
b = map(lambda x: x+2, a)
b = list(b) #结果是[3, 4, 5]
'''

在3.x需要b = list(b)这一步,在2.x不需要这步,原因是在3.x中,map函数仅仅是创建一个待运行的命令容器,只有其他函数调用它的时候才返回结果。

'''
也就是说,我们首先定义一个函数,然后再用map()命令将函数逐一应用到(map)列表中的每个元素,最后返回一个数组。map()命令也接受多参数的函数,如map(lambda x,y: x*y, a, b)表示将a、b两个列表的元素对应相乘,把结果返回给新列表。

也许有的读者会疑问,有了列表解析,为什么还要有map()命令呢?其实列表解析虽然代码简短,但是本质上还是for命令,而Python的for命令效率并不高,而map()函数实现了相同的功能,并且效率更高,原则上来说,它的循环命令速度相当于C语言。

接着是reduce()函数。它有点像map()函数,但map()函数用于逐一遍历,而是reduce()函数用于递归计算。先给出一个例子,这个例子可以算出n的阶乘:

reduce(lambda x,y: x*y, range(1, n+1))

(注:在2.x中,上述命令可以直接运行,在3.x中,reduce函数已经被移出了全局命名空间,它被置于fuctools库中,如需使用,则要通过from fuctools import reduce引入reduce)

其中,range(1, n+1)相当于给出了一个列表,元素是1~n这n个整数。lambda x, y: x*y构造了一个二元函数,返回两个参数的乘积。reduce命令首先将列表的前两个元素作为函数的参数进行运算,然后将运算结果与第三个数字作为函数的参数,然后再将运算结果与第四个数字作为函数的参数……依此递推,直到列表结束,返回最终结果。如果用循环命令,那就要写成:

s = 1
for i in range(1, n+1):
 s = s * i

最后是filter()函数。顾名思义,它是一个过滤器,用来筛选出列表中符合条件的元素,例如,

b = filter(lambda x: x > 5 and x < 8, range(10))
b = list(b) #结果是[6, 7],在3.x需要b = list(b)这一步,在2.x不需要这步,理由同map

使用filter()函数首先需要一个返回值为bool型的函数,如上述的lambda x: x > 5 and x < 8定义了一个函数,判断x是否大于5且小于8,然后将这个函数作用到range(10)的每个元素中,如果为True,则“挑出”那个元素,最后将满足条件的所有元素组成一个列表返回。

当然,上述filter语句,可以用列表解析写为:

b = [i for i in range(10) if i > 5 and i < 8]

它并不比filter语句复杂。但是要注意,我们使用map()、reduce()或filter(),最终目的是兼顾简洁和效率,因为map()、reduce()或filter()的循环速度比Python内置的for或while循环要快得多。

您对本文章有什么意见或着疑问吗?请到论坛讨论您的关注和建议是我们前行的参考和动力  
上一篇:2.2.2 基本命令
下一篇:2.2.4 库的导入与添加
相关文章
图文推荐
排行
热门
最新书评
特别推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站