利用Python进行数据分析笔记:3.1数据结构
一、元组
元组是一种固定长度、不可变的Python对象序列。创建元组最简单的办法是用逗号分隔序列值:
tup = 4, 5, 6
tup
Out[52]: (4, 5, 6)
### 通过更复杂的表达式定义元组需要用括号将值抱起来:
nested_tup = (4, 5, 6), (7, 8)
nested_tup
Out[55]: ((4, 5, 6), (7, 8))
tuple
函数将任意序列或迭代器转换为元组:
tuple([4, 0, 2])
Out[56]: (4, 0, 2)
tup = tuple('string')
tup
Out[58]: ('s', 't', 'r', 'i', 'n', 'g')
中括号[]
可以获取元组的元素,Python中序列索引从0开始:
tup[0]
Out[59]: 's'
元组一旦创建,各个位置上的对象是无法被修改的,如果元组的一个对象是可变的,例如列表,你可以在它内部进行修改:
tup = tuple(['foo', [1, 2], True])
tup
Out[61]: ('foo', [1, 2], True)
tup[2] = False
TypeError: 'tuple' object does not support item assignment
tup[1].append(3)
tup
Out[64]: ('foo', [1, 2, 3], True)
可以使用+
号连接元组来生成更长的元组:
(4, None, 'foo') + (6, 0) + ('bar', )
Out[65]: (4, None, 'foo', 6, 0, 'bar')
元组乘以整数,则会和列表一样,生成含有多份拷贝的元组:
('foo', 'bar') * 4
Out[66]: ('foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'bar')
### 注意对象自身并没有复制,只是指向它们的引用进行了复制
1. 元组拆包
将元组型的表达式赋值给变量,Python会对等号右边的值进行拆包:
tup = (4, 5, 6)
a, b, c = tup
a
Out[84]: 4
b
Out[85]: 5
c
Out[86]: 6
### 嵌套元组也可以拆包:
tup = 4, 5, (6, 7)
a, b, (c, d) = tup
d
Out[89]: 7
### 使用这个功能可以轻易交换变量名:
a, b = 1, 2
a
Out[91]: 1
b
Out[92]: 2
b, a = a, b
a
Out[94]: 2
b
Out[95]: 1
拆包的一个常用场景就是遍历元组或列表组成的序列:
seq = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
for a, b, c in seq:
print('a={0}, b={1}, c={2}'.format(a, b, c))
a=1, b=2, c=3
a=4, b=5, c=6
a=7, b=8, c=9
*rest
用于在函数调用时获取任意长度的位置参数列表:
values = 1, 2, 3, 4, 5
a, b, *rest = values
a, b
Out[111]: (1, 2)
rest
Out[112]: [3, 4, 5]
###rest这个变量名并没有特殊之处,为了方便很多人使用下划线(_)来表示不想要的变量:
a, b, *_ = values
2. 元组方法
count
用于计量某个数值在元组中出现的次数:
a = (1, 2, 2, 2, 3, 4, 2)
a.count(2)
Out[114]: 4
二、 列表
列表的长度可变,内容可以修改。可以使用[]
或者list
类型函数来定义列表:
a_list = [2, 3, 7, None]
tup = ('foo', 'bar', 'baz')
b_list = list(tup)
b_list
Out[121]: ['foo', 'bar', 'baz']
b_list[1]
Out[122]: 'bar'
b_list[1] = 'peekaboo'
b_list
Out[124]: ['foo', 'peekaboo', 'baz']
### list函数常用于将迭代器或者生成器转化为列表:
gen = range(10)
gen
Out[127]: range(0, 10)
list(gen)
Out[128]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1. 增加和移除元素
append
方法将元素添加到列表尾部:
b_list.append('dwarf')
b_list
Out[130]: ['foo', 'peekaboo', 'baz', 'dwarf']
insert
方法可以将元素插入到指定列表位置:
(插入位置范围在0到列表长度之间)
b_list.insert(1, 'red')
b_list
Out[132]: ['foo', 'red', 'peekaboo', 'baz', 'dwarf']
### insert与append相比计算代价更高。
pop
是insert
的反操作,将特定位置的元素移除并返回:
b_list.pop(2)
Out[133]: 'peekaboo'
b_list
Out[134]: ['foo', 'red', 'baz', 'dwarf']
remove
方法会定位第一个符合要求的值并移除它:
b_list.append('foo')
b_list
Out[136]: ['foo', 'red', 'baz', 'dwarf', 'foo']
b_list.remove('foo')
b_list
Out[138]: ['red', 'baz', 'dwarf', 'foo']
in
关键字可以检查一个值是否在列表中;
not in
表示不在:
'dwarf' in b_list
Out[139]: True
'dwarf' not in b_list
Out[140]: False
2. 连接和联合列表
+
号可以连接两个列表:
[4, None, "foo"] + [7, 8, (2, 3)]
Out[141]: [4, None, 'foo', 7, 8, (2, 3)]
extend
方法可以向该列表添加多个元素:
x = [4, None, 'foo']
x.extend([7, 8, (2, 3)])
x
Out[144]: [4, None, 'foo', 7, 8, (2, 3)]
使用extend
将元素添加到已经存在的列表是更好的方式,比+
快。
3. 排序
sort
方法可以对列表进行排序:
a = [7, 2, 5, 1, 3]
a.sort()
a
Out[151]: [1, 2, 3, 5, 7]
key
可以传递一个用于生成排序值的函数,例如通过字符串的长度进行排序:
b = ['saw', 'small', 'He', 'foxes', 'six']
b.sort(key=len)
b
Out[158]: ['He', 'saw', 'six', 'small', 'foxes']
4. 二分搜索和已排序列表的维护
bisect.bisect
找到元素应当被插入的位置,返回位置信息
bisect.insort
将元素插入到已排序列表的相应位置保持序列排序
import bisect
c = [1, 2, 2, 2, 3, 4, 7]
bisect.bisect(c, 2)
Out[161]: 4
bisect.bisect(c, 2)
Out[162]: 4
bisect.bisect(c, 5)
Out[163]: 6
bisect.insort(c, 6)
c
Out[165]: [1, 2, 2, 2, 3, 4, 6, 7]
bisect
模块的函数并不会检查列表是否已经排序,因此对未排序列表使用bisect不会报错,但是可能导致不正确结果
5. 切片
切片符号可以对大多数序列类型选取子集,基本形式是[start:stop]
起始位置start索引包含,结束位置stop索引不包含
seq = [7, 2, 3, 7, 5, 6, 0, 1]
seq[1:5]
Out[167]: [2, 3, 7, 5]
切片还可以将序列赋值给变量:
seq[3:4] = [6, 3]
seq
Out[169]: [7, 2, 3, 6, 3, 5, 6, 0, 1]
start和stop可以省略,默认传入起始位置或结束位置,负索引可以从序列尾部进行索引:
seq[:5]
Out[170]: [7, 2, 3, 6, 3]
seq[3:]
Out[171]: [6, 3, 5, 6, 0, 1]
seq[-4:]
Out[172]: [5, 6, 0, 1]
seq[-6:-2]
Out[173]: [6, 3, 5, 6]
步进值step
可以在第二个冒号后面使用, 意思是每隔多少个数取一个值:
seq[::2]
Out[174]: [7, 3, 3, 6, 1]
对列表或元组进行翻转时,一种很聪明的用法时向步进值传值-1:
seq[::-1]
Out[175]: [1, 0, 6, 5, 3, 6, 3, 2, 7]
三、字典
dict(字典)可能是Python内建数据结构中最重要的,它更为常用的名字是哈希表或者关联数组。
字典是键值对集合,其中键和值都是Python对象。
{}
是创建字典的一种方式,字典中用逗号将键值对分隔:
empty_dict = {}
d1 = {'a' : 'some value', 'b' : [1, 2, 3, 4]}
d1
Out[3]: {'a': 'some value', 'b': [1, 2, 3, 4]}
你可以访问、插入或设置字典中的元素,:
d1[7] = 'an integer'
d1
Out[9]: {'a': 'some value', 'b': [1, 2, 3, 4], 7: 'an integer'}
d1['b']
Out[10]: [1, 2, 3, 4]
in
检查字典是否含有一个键:
'b' in d1
Out[11]: True
del
或pop
方法删除值,pop
方法会在删除的同时返回被删的值,并删除键:
d1[5] = 'some value'
d1
Out[25]: {'a': 'some value', 'b': [1, 2, 3, 4], 7: 'an integer', 5: 'some value'}
d1['dummy'] = 'another value'
d1
Out[27]:
{'a': 'some value',
'b': [1, 2, 3, 4],
7: 'an integer',
5: 'some value',
'dummy': 'another value'}
del d1[5]
d1
Out[29]:
{'a': 'some value',
'b': [1, 2, 3, 4],
7: 'an integer',
'dummy': 'another value'}
ret = d1.pop('dummy')
ret
Out[31]: 'another value'
d1
Out[32]: {'a': 'some value', 'b': [1, 2, 3, 4], 7: 'an integer'}
update
方法将两个字典合并:
update方法改变了字典元素位置,对于字典中已经存在的键,如果传给update方法的数据也含有相同的键,则它的值将会被覆盖。
d1.update({'b':'foo', 'c':12})
d1
Out[34]: {'a': 'some value', 'b': 'foo', 7: 'an integer', 'c': 12}
1. 从序列生成字典
mapping = dict(zip(range(5), reversed(range(5))))
mapping
Out[36]: {0: 4, 1: 3, 2: 2, 3: 1, 4: 0}
2. 有效的字典键类型
字典的值可以是任何Python对象,但键必须是不可变的对象,比如标量类型(整数、浮点数、字符串)或元组(且元组内对象也必须是不可变对象)。
通过 hash
函数可以检查一个对象是否可以哈希化(即是否可以用作字典的键):
hash('string')
Out[37]: -5468203287278174667
hash((1, 2, (2, 3)))
Out[38]: -9209053662355515447
hash((1, 2, [2, 3]))#### 会因为列表是可变的失败
TypeError: unhashable type: 'list'
##### 为了将列表作为键,一种方式就是将其转换为元组
### 元组只要它内部元素都可以哈希化,则它自己也可以哈希化:
d = {}
d[tuple([1, 2, 3])] = 5
d
Out[42]: {(1, 2, 3): 5}
四、集合
集合是一种无序且元素唯一的容器。
1. 集合创建
set
函数或者是用字面值集与大括号,创建集合:
set([2, 2, 2, 1, 3, 3])
Out[43]: {1, 2, 3}
{2, 2, 2, 1, 3, 3}
Out[44]: {1, 2, 3}
2. 集合操作:联合、交集、差集、对称差集
union
方法或|
二元操作符获得两个集合的联合即两个集合中不同元素的并集:
a = {1, 2, 3, 4, 5}
b = {3, 4, 5, 6, 7, 8}
a.union(b)
Out[48]: {1, 2, 3, 4, 5, 6, 7, 8}
a | b
Out[49]: {1, 2, 3, 4, 5, 6, 7, 8}
intersection
方法或&
操作符获得交集即两个集合中同时包含的元素:
a.intersection(b)
Out[50]: {3, 4, 5}
a & b
Out[51]: {3, 4, 5}
常用的集合方法列表:
Python集合操作
3. 集合的元素
和字典类似,集合的元素必须是不可变的。如果想要包含列表型的元素,必须先转换为元组:
my_data = [1, 2, 3, 4]
my_set = {tuple(my_data)}
my_set
Out[54]: {(1, 2, 3, 4)}