用Python玩转数据笔记

第一个Python程序

Python输出:print()函数

myString = 'Hello, World!'
print(myString) # Python3写法
print myString # Python2写法

Python输入:input()函数,返回的类型是字符型

# input()函数的参数就是提示语
price = input('input the stock price of Apple:')
# input the stock price of Apple:109
price
# '109'
type(price)
# <class 'str'>
price = int(input('input the stock price of Apple:'))
price = eval(input('input the stock price of Apple:'))
# eval()把值当做有效的Python表达式并计算出结果

续行符’\’

if(signal == 'red') and\
(car == 'moving'):
car = 'stop'
elif(signal == 'green' and\
(car == 'stop'):
car = 'moving'
# 等价于
if(signal == 'red') and (car == 'moving'):
car = 'stop'
elif(signal == 'green' and (car == 'stop'):
car = 'moving'

不需要续行符可以直接换行的两种情况:

  • 小括号、中括号、花括号内部
  • 三引号包括下的字符串

数据类型

整型

整型和长整型并不严格区分,整型的长度和机器字长有关,如32位机器上标准整型是2-31到231-1。长整型范围远超C语言和其他编译型语言中的长整型,跟内存大小有关,基本没有溢出错误。在Python2.2之后没有明确的整型和长整型区分了。

布尔型

是整型的子集,只有2个值:True和False,本质是用1和0储存的。

浮点型

即数学中的实数,可以用科学计数法表示。

3.22 # 3.22
9.8e3 # 9800.0
-4.78e-2 # -0.0478
type(-4.78e-2) # <class 'float'>

复数型

虚数部分必须有j

2.4+5.6j #(2.4+5.6j)
type(2.4+5.6j) # <class 'complex'>
3j # 3j
type(3j) # <class 'complex'>
5+0j # 5+0j
type(5+0j) # <class 'complex'>
x = 2.4+5.6j
x.imag # 5.6 虚数部分
x.real # 2.4 实数部分
x.conjugate() # (2.4-5.6j) 共轭复数

序列类型

  • 字符串:单引号、双引号、三引号内的都是字符串,属于不可变类型。在三引号中可以使用单引号或者双引号。
  • 列表:强大的类型,用方括号[]界别,属于可变类型。
  • 元组:与列表类似,用小括号()界别,属于不可变类型。

映射类型 字典

用大括号{}界别,类似于哈希表的键值对。

d = {'sine':'sin', 'cosine':'cos', 'PI':3.14159}
d['sine'] # 'sin'

基本计算

算术运算

按优先级顺序:乘方**、正负号+-、乘除*/、整除//、取余%、加减+-

比较运算

数值的比较:按值比较大小

3 < 4 < 7 # True, 等价于(3 < 4) and (4 < 7)
4 > 3 == 3 # True, 等价于(4 > 3) and (3 == 3)
4 < 3 < 5 != 2 < 7 # False

字符串的比较:按照ASCII码值比较大小

2 == 2 # True
2.46 <= 8.33 # True
'abc' == 'xyz' # False
'abc' > 'xyz' # False
'abc' < 'xyz' # True

逻辑运算符

逻辑运算符的优先级:not、and、or

x, y = 3.1415926536, -1024
x < 5.0 # True
not(x < 5.0) # False
(x < 5.0) or (y > 2.718281828) # True
(x < 5.0) and (y > 2.718281828) # False
not(x is y) # True
3 < 4 < 7 # True, 等价于(3 < 4) and (4 < 7)

字符运算符

原始字符串操作符(r/R):用于一些不希望转义字符起作用的地方。

f = open('c:\python\test.py', 'w') # error!
f = open(r'c:\python\test.py', 'w') # correct
f = open('c:\\python\\test.py', 'w') # correct

综合运算

3 < 2 and 2 < 1 or 5 > 4 # True
x + 3/y - z%2 > 2 # False
3 - 2 << 1 # 2
3 - 2 << 1 < 3 # True

函数、模块和包

内建函数

可以通过在命令行输入dir(__builtins__)查看有哪些内建函数,str()和type()适用于所有标准类型。

数值型内建函数

  • abs()
  • bool()
  • oct()
  • round():四舍五入
  • int()
  • hex()
  • divmod()
  • ord()
  • pow()
  • float()
  • chr()
  • complex()

实用函数

  • dir()
  • input()
  • help():查看函数用法,例如help(zip)
  • open()
  • len()
  • range()

模块

非内建函数需要导入函数所在的模块。

from math import *
floor(-35.4) # -36,向下取整
floor(-35.5) # -36
floor(-35.8) # -36

一个完整的Python文件即一个模块。
“文件”是物理上的组织方式,如math.py
“模块”是逻辑上的组织方式,如math

Python通常使用“import 模块”的方式将现成模块中的函数、类等重用到其他代码块中。

import math
math.pi # 3.1415926
import ModuleName # 导入单个模块
import ModuleName1, ModuleName2, ... # 导入多个模块
from ModuleName import ModuleElement # 导入某个模块属性

是一个有层次的文件目录结构,定义了一个由模块和子包组成的Python应用程序执行环境。

AAA/
bbb.py
CCC/
c1.py
c2.py
import AAA.CCC.c1
AAA.CCC.c1.func1(123)
from AAA.CCC.c1 import func1
func1(123)

库是一组具有相关功能的模块的集合。

条件语句

if语句

# 语法
if expression:
expr_true_suite # 条件为真时执行,代码块必须缩进(通常为4个空格)

else语句

# 语法
if expression:
expr_true_suite
else:
expr_false_suite

elif语句

# 语法
if expression:
expr_true_suite
elif expression2:
expr2_true_suite
.
.
.
elif expressionN:
exprN_true_suite
else:
none_of_the_above_suite

range()函数

# 语法
range(start, end, step=1) # start起始值(包含),end终值(不包含),step步长(不能为0)
range(start, end) # 缺省step值为1
range(end) # 缺省了start值为0,step为1

range()函数产生一系列的整数,返回一个range对象,range对象是可迭代的。

list(range(3,11,2) # [3,5,7,9]
list(range(3,11) # [3,4,5,6,7,8,9,10]
list(range(11)) # [0,1,2,3,4,5,6,7,8,9,10]

循环

while循环

# 语法
while expression:
suite_to_repeat

for循环

# 语法
for iter_var in iterable_object:
suite_to_repeat

可迭代的对象包括String、List、Tuple、Dictionary、File、range()的返回值。

s = 'python'
for c in s:
print(c)
for i in range(3,11,2):
print(i, end=' ')
# 输出3 5 7 9

for循环除了可以遍历一个数据集中的成员,也可以在列表解析及生成器表达式中使用。

# 列表解析
[i for i in range(10)] # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[i+1 for i in range(10) if i%2==0] # [1, 3, 5, 7, 9]
# 生成器表达式
(i+1 for i in range(10) if i%2==0) # <generator object <genexpr> at 0x000...>

在数据量较小的时候用列表解析,数据量大时用生成器表达式。

循环中的break,continue,else

break语句,跳出循环。

sumA = 0
i = 1
while True:
sumA += i
i += 1
if sumA > 10:
break
print('i={},sum={}'.format(i,sumA) # i=6,sumA=15

continue结束当前轮循环,继续下一轮循环。

循环中的else:如果循环代码从break处终止,跳出循环,不执行else语句。如果正常结束循环,则执行else中代码。

from random import randint
x = randint(0, 300)
go = 'y'
while(go == 'y'):
digit = int(input('Please input a number between 0~300:'))
if digit == x:
print('Bingo!')
break
elif digit > x:
print('Too large, please try again.')
else:
print('Too small, please try again.')
print('Input y if you want to continue.')
go = input()
print(go)
else:
print('Goodbye!')

自定义函数

# 语法
def function_name([arguments]):
"optional documentation string"
function_suite

其中DocString(函数描述)可以通过fn.__doc__查看。

def addMe2Me(x):
'apply operation + to argument'
return (x+x)
addMe2Me(3.7) # 7.4
addMe2Me(5) # 10
addMe2Me('Python') # 'PythonPython'

关键字参数

一旦使用,则后面都需要用关键字参数。关键字参数上让调用者通过参数名区分参数,允许改变参数列表中的参数顺序。

def f(x,y):
''' x and y both correct words or not'''
if y:
print(x, 'and y both correct')
print(x, 'is OK')
f(68, False) # 68 is OK
f(y=False, x=68) # 68 is OK

传递函数

def addMe2Me(x):
return (x+x)
def self(f, y):
print(f(y))
self(addMe2Me, 2.2) # 4.4

lambda函数(匿名函数)

r = lambda x : x+x
r(5) # 10

Python常用标准库函数

math库

import math
math.pi # 3.1415
math.e # 2.7182
math.ceil(3.6) # 4, 向上取整
math.floor(3.6) # 3, 向下取整
math.pow(2,3) # 8, x的y次方
math.sqrt(4) # 2.0, 开方
math.degrees(3.14) # 179.90 将弧度转成角度
math.radians(180) # 3.1415 将角度转成弧度

os库

提供跟操作系统交互的函数。

import os
os.getcwd() # 获得当前工作目录
path = 'c:\\test'
os.chdir(path) # 修改工作目录到path
os.rename('test.txt','test1.txt') # 将test.txt文件名修改为test1.txt
os.remove('test1.txt') # 删除文件test1.txt

random库

import random
random.choice(['C++', 'Java', 'Python'] # 从序列中获取一个随机值
random.randint(1, 100) # 生成1-100之间的随机整数
random.randrange(0, 10, 2) # 从range中生成一个随机整数
random.random() # 生成一个[0,1.0)之间的随机浮点数
random.uniform(5, 10) # 生成一个5-10之间的随机浮点数
random.sample(range(100), 10) # 从range中获取指定个数(10个)的随机值,用列表返回
nums = [1001, 1002, 1003, 1004, 1005]
random.shuffle(nums) # 将列表中的元素顺序打乱

datetime库

import datetime
from datetime import date
date.today() # datetime.date(2017, 4, 30)
from datetime import time
tm = time(23, 20, 35)
print(tm) # 23:20:35
from datetime import datetime
dt = datetime.now()
dt # datetime.datetime(2017, 4, 30, 15, 0, 10, 540148)
print(dt.strftime('%a, %b %d %Y %H:%M') # Sun, Apr 30 2017 15:00
dt = datetime(2017,6,6,23,29)
print(dt) # 2017-06-06 23:29:00
ts = dt.timestamp()
ts # 1496762940.0, 转换成时间戳
print(datetime.fromtimestamp(ts)) # 2017-06-06 23:29:00 把时间戳转成本地时间

异常(Exception)

Python中每个异常都是类的实例,用异常对象(exception object)表示异常情况。

用try-except语句对异常进行捕捉处理。

while True:
try:
num1 = int(input('Enter the first number:'))
num2 = int(input('Enter the second number:'))
print(num1 / num2)
break
except ValueError:
print('Please input a dight!')
except Zero DivisionError as err:
print('The second number cannot be zero!')
print(err)
else:
print('Aha, everything is OK.')

上下文管理器(context manager)和with语句

try:
f = open('data.txt')
for line in f:
print(line, end = '')
except IOError:
print('Cannot open the file!')
finally:
f.close()

这种情况下加入f都不能正常打开了,程序还是会发生异常,所以可以用上下文管理器。上下文管理器可以定义和控制代码块执行前的准备动作和执行后的收尾动作。

with open('data.txt') as f:
for line in f:
print(line, end='')

本地数据获取

文件读写

  • file_obj = open(filename, mode=’r’, buffering=-1, …)

用于文件打开,其他参数可以通过help(open)获取,比如其他常用的还有encoding。
mode为可选参数,默认为r。
buffering也为可选参数,默认值为-1(-1表示按照默认大小缓冲,0表示不缓冲,1或者大于1的值表示缓冲一行或指定缓冲区大小)。二进制文件可以不使用缓冲,文本文件必须缓冲。

open()函数-mode

mode function
r 以读模式打开
w 以写模式打开(清空原内容)
a 以追加模式打开(从EOF开始,必要时创建新文件
r+ 以读写模式打开
w+ 以读写模式打开(清空原内容)
a+ 以读和追加模式打开
rb 以二进制读模式打开
wb 以二进制写模式打开(参见w)
ab 以二进制追加模式打开(参见a)
rb+ 以二进制读写模式打开(参见r+)
wb+ 以二进制读写模式打开(参见w+)
ab+ 以二进制读写模式打开(参见a+)

open函数返回一个文件(file)对象,文件对象是可迭代的,有关闭和读写文件相关的函数/方法。

  • file_obj.write(str)
with open('firstpro.txt','w') as f:
f.write('hello, world')
  • file_obj.read(size) / file_obj.read()
with open('firstpro.txt') as f:
p1 = f.read(5) # 从文件中至多读出size字节数据,返回一个字符串
p2 = f.read() # 读文件直到文件结束,返回一个字符串
print(p1,p2)

with语句会主动关闭文件句柄,所以不需要写f.close()来关闭文件。

  • file_obj.readlines(),返回结果是一个列表。
  • file_obj.readline()
  • file_obj.writelines()

文件读写例子:将companies.txt的字符串前加上序号1、2、3…后写到另一个文件scompanies.txt中。

# Filename: revcopy.py
with open('companies.txt') as f1:
cNames = f1.readlines()
for i in range(0, len(cNames)):
cNames[i] = str(i+1) + ' ' + cNames[i]
with open('scompanies.txt','w') as f2:
f2.writelines(cNames)

在文件尾部加上数据,并把新的数据读出来。

# Filename: companies_b.py
s = 'Tecent Technology Company Limited'
with open('companies.txt', 'a+') as f:
f.writelines('\n')
f.writelines(s)
cNames = f.readlines()
print(cNames)

以上函数并不能实现这个功能,因为运行f.writelines(s)文件指针已经在文件的末尾,再read读取不到数据。

  • file_obj.seek(offest, whence=0) 在文件中移动文件指针,从whence(0表示文件头部,1表示当前位置,2表示文件尾部)偏移offest个字节。所以上面的代码可以修改成如下,以实现功能。
# Filename: companies_b.py
s = 'Tecent Technology Company Limited'
with open('companies.txt', 'a+') as f:
f.writelines('\n')
f.writelines(s)
f.seek(0)
cNames = f.readlines()
print(cNames)

标准文件

  • stdin 标准输入
  • stdout 标准输出
  • stderr 标准错误

stdin和stdout实际是通过sys模块,如sys.stdout.write('hello')处理的,平时会用input和print。

网络数据获取

网络数据获取通过抓取网页,解析网页内容获取。

import requests
r = requests.get('https://book.douban.com/subject/1084336/comments/')
r.status_code # 200
r.text # 显示页面内容
r.json() # 如果数据格式是json,可以这样解码
r.content # 如果数据是二进制的,可以这样解码,如二进制创建的图片
r.encoding='utf8' # 修改文本编码

BeautifulSoup

BeautifulSoup是一个可以从HTML或XML文件中提取数据的Python库。

from bs4 import BeautifulSoup
markup = '<p class="title"><b>The Little Prince</b></p>'
soup = BeautifulSoup(markup, "lxml")
# 得到标签<b>的内容
soup.b # <b>The Little Prince</b>
# 查看标签<b>类型
type(soup.b) # bs4.element.Tag
tag = soup.p
# 获取tag名字
tag.name # p
# 获取tag属性
tag.attrs # {'class':[title]}
# tag和字典相同,也可以通过以下方式获取属性
tag['class'] # ['title']
# 提取非属性字符串
tag.string # 'The Little Prince'
type(tag.string) # bs4.element.NavigableString
# find_all()方法,寻找所有包含有某个tag的内容
soup.find_all('b') # [<b>The Little Prince</b>]

结合前面爬取的数据,获取《小王子》这本书的评论。

import requests
from bs4 import BeautifulSoup
r = request.get('https://book.douban.com/subject/1084336/comments/')
soup = BeautifulSoup(r.text, 'lxml')
# 观察发现所有评论都是在p标签,属性comment-content里的
pattern = soup.find_all('p', 'comment-content')
for item in pattern:
print(item.string)
pattern_s = re.compile('<span class="user-stars allstar(.*?)rating"')
p = re.findall(pattern_s, r.text)
for star in p:
sum += int(star)
print(sum)

序列

序列类型运算符

week = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
print week[1] # Tuesday
print week[-2] # Saturday
print week[1:4] # ['Tuesday', 'Wednesday', 'Thursday']
print week[:6] # ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
print week[::-1]
# ['Sunday', 'Saturday', 'Friday', 'Thurday', 'Wednesday', 'Tuesday', 'Monday']
'apple'*3 # appleappleapple
'pine'+'apple' # pineapple
'BA' in ('BA', 'The Boeing Company', '122.64') # True
'BA' not in ('BA', 'The Boeing Company', '122.64') # False

序列类型转换内建函数

  • list()
  • str()
  • tuple()
# 字符串转列表
list('Hello, World!') # ['H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!']
# 字符串转元组
tuple('Hello, World!') # ('H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!')
  • enumerate() 返回一个enumerate对象,它的元素由元素的索引和值构成的一个个元组
  • reversed() 序列逆序
  • len() 求序列元素个数
  • sorted() 对序列进行排序
  • max() 求序列中最大值
  • sum() 序列求和
  • min() 求序列中最小值
  • zip() 由一系列可迭代对象作为参数,返回一个zip对象,它把对象对应的元素打包成一个个元组
aStr = 'Hello World!'
len(aStr) # 13
sorted(aStr) # [' ', '!', 'H', 'W', 'd', 'e', 'l', 'l', 'l', 'o', 'o', 'r']

字符串

例子:将字符串”Hello, World!”中的”World”替换成”Python”,并计算其包含的标点符号(包括逗号、句号、感叹号、问号)的个数。

# Filename: puncount.py
aStr = "Hello, World!"
bStr = aStr[:7] + "Python!"
count = 0
for ch in bStr[:]:
if ch in ',.!?':
count += 1
# C语言风格格式化输出 format_string %(arguments_to_convert)
print('There are %d punctuation marks.'%(count))
# 更常用的格式化输出形式 format_string.format(argument_to_convert)
# {0:d}称为格式限定符,其中0表示序号,可以不按顺序,d是格式说明符
print('There are {0:d} punctuation marks.'.format(count))

类型说明符

字符 描述
b 二进制,以2为基数输出数字
o 八进制,以8为基数输出数字
x 十六进制,以16为基数输出数字
c 字符,将整数转换成对应的Unicode字符输出
d 十进制整数,以10位基数输出数字
f 浮点数,以浮点数输出数字
e 指数记法,以科学计数法输出数字,用e表示幂

常用格式说明符

符号 描述
+m.nf 输出带符号(若正整数输出”+”号)的数,保留n位小数,整个输出占m列(若实际宽度超过m,则突破m的限制)
< 左对齐,默认用空格填充右边
0>5d 右对齐,用0填充左边,宽度为5
^ 居中对齐

[对齐说明符][符号说明符][最小宽度说明符][.精度说明符][类型说明符]
注:整数默认右对齐,字符串默认左对齐。

age, height = 21, 1.758
print("Age:{0:<5d}, Height{1:5.2f}". format(age,height) # Age:21 , Height: 1.76

字符串的应用例子:判断字符串是否为回文字符串

sStr = "acdhdca"
if (sStr == ''.join(reversed(sStr))):
print('Yes')
else:
print('No')
import operator
sStr = "acdhdca"
if operator.eq(sStr, ''.join(reversed(sStr)))==0:
print('Yes')
else:
print('No')
sStr = "acdhdca"
if sStr == sStr[::-1]:
print('Yes')
else:
print('No')

常用字符串操作函数举例

song = "Blowing in the wind"
song.find("the") # 11
song.find("the", 8, 12) # -1
song.lower() # 'blowing in the wind' 只是中间结果,不改变原始字符串
song.split(' ') # ['Blowing', 'in', 'the', 'wind']
song.replace("the","that") # Blowing in that wind
aList = ["hello", "world"]
' '.join(aList) # 'hello world' .join前面的表示分隔字符,这里是空格
y = "你好"
z = y.encode('utf-8')
z # b'\xe4\xbd\xa0\xe5\xa5\xbd'
t = z.decode()
t # '你好'

练习1. 使用以下语句存储一个字符串:str = ‘My moral standing is: 0.98765’
将其中的数字字符串转换成浮点数并输出。(提示:可以使用find方法和字符串切片,提取出字符串中冒号后面的部分,然后使用float函数,将提取出来的字符串转换为浮点数)

str = 'My moral standing is: 0.98765'
index = str.find(':')
float(str[index+1:])

练习2. 输入一个字符串“I like Python very much 2333 because Python is very cute 666.”,判别该字符串中数字字符和单词的个数,并将第一次出现的Python替换成你偶像的名字并输出新字符串。

str = "I like Python very much 2333 because Python is very cute 666."
sList = str.split(' ')
dCount = 0
sCount = 0
for s in sList:
if s.isdigit():
dCount += 1
else:
sCount += 1
print('The count of digits is {:d}.\nThe count of string is {:d}.'.format(dCount, sCount))
str = str.replace("Python", "C++", 1)
print(str)

列表

例子1:某学校组织了一场校园歌手比赛,每个歌手的得分由10位评委和观众决定,最终得分是去掉10名评委的一个最高分和一个最低分,再加上所有观众评委分数后的平均值。评委打出的10个分数为:9、9、8.5、10、7、8、8、9、8和10,观众评委打出的综合评分为9,请计算该歌手的最终得分。

jScores = [9,9,8.5,10,7,8,8,9,8,10]
aSorre = 9
jScores.sort() # 如果使用sorted(jScores),则不会改变原列表的值
jScores.pop()
jScores.pop(0)
jScores.append(aScore)
aveScore = sum(jScore)/len(jScores)
print(aveScore)

例子2:将工作日([‘Monday’, ‘Tuesday’, ‘Wednesday’, ‘Thursday’, ‘Friday’])和周末([‘Saturday’, ‘Sunday’])的表示形式合并,并将它们用序号标出并分行显示。

week = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
weekend = ['Saturday', 'Sunday']
week.extend(weekend) # 注:这里不能用append,不然会以一个列表的方式添加,而不是两个元素
for i,j in enumerate(week):
print(i+1, j)

列表方法中参数的作用:
如list.sort(key=None, reverse=False)

numList = [3,11,5,8,16,1]
fruitList = ['apple', 'banana', 'pear', 'lemon', 'avocado']
numList.sort(reverse = True)
numList # [16, 11, 8, 5, 3, 1]
fruitList.sort(key = len)
fruitList # ['pear', 'apple', 'lemon', 'banana', 'avocado']

列表解析

[x for x in range(10)] # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[x ** 2 for x in range(10)] # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
[x ** 2 for x in range(10) if x ** 2 < 50] # [0, 1, 4, 9, 16, 25, 36, 49]
[(x+1,y+1) for x in range(2) for y in range(2)] # [(1, 1), (1, 2), (2, 1), (2, 2)]

生成器表达式

sum(x for x in range(10)) # 45

元组

元组主要用在下面三种情况中:

  • 在映射类型中当作键使用
  • 函数的特殊类型参数
def foo(args1, *argst):
print(args1)
print(argst)
foo('Hello,', 'Wangdachui', 'Niuyun', 'Linling')
# Hello,
# ('Wangdachui', 'Niuyun', 'Linling')
  • 作为函数的特殊返回值
def foo():
return 1,2,3
foo() # (1,2,3)

字典

字典是Python中唯一內建的映射类型,每个元素形成key-value对。

# 直接创建字典
aInfo = {'Wangdachui':3000, 'Niuyun':2000, 'Linling':4500, 'Tianqi':8000}
# 通过列表创建
info = [('Wangdachui',3000), ('Niuyun',2000), ('Linling',4500), ('Tianqi',8000)]
bInfo = dict(info)
cInfo = dict([['Wangdachui',3000], ['Niuyun',2000], ['Linling',4500], ['Tianqi',8000]])
dInfo = dict(Wangdachui=3000, Niuyun=2000, Linling=4500, Tianqi=8000)

创建字典

aDict = {}.fromkeys(('Wangdachui','Niuyun','Liling','Tianqi'),3000)
sorted(aDict) # ['Liling', 'Niuyun', 'Tianqi', 'Wangdachui']

生成字典

names = ['Wangdachui', 'Niuyun', 'Liling', 'Tianqi']
salaries = [3000, 2000, 4500, 8000]
dict(zip(names, salaries))

字典基本操作

aInfo = {'Wangdachui':3000, 'Niuyun':2000, 'Linling':4500, 'Tianqi':8000}
aInfo['Niuyun'] # 2000,键值查找
aInfo['Niuyun'] = 9999 # 更新数据
aInfo['Fuyun'] = 1000 # 添加数据
'Mayun' in aInfo # False,成员判断
del aInfo['Fuyun'] # 删除字典成员
len(aInfo) # 4
hash('Wangdachui') # 判断某一对象是否能Hash,可理解为是否可变
aInfo.keys() # 输出所有的键
aInfo.values() # 输出所有的值
for k,v in aInfo.items(): # .items()将字典中的每个元素组成一个元组,并放到列表中返回
print(k,v)
# 更新数据表
aInfo = {'Wangdachui':3000, 'Niuyun':2000, 'Linling':4500}
bInfo = {'Wangdachui':4000, 'Niuyun':9999, 'Wangzi':6500}
aInfo.update(bInfo)
aInfo # {'Wangdachui': 4000, 'Niuyun': 9999, 'Linling': 4500, 'Wangzi': 6500}
# 键值查找
stock = {'AXP':78.51, 'BA':184.76}
stock['AAA'] # 会发生异常
print(stock.get('AAA')) # None
# 删除字典
aStock = {'AXP':78.51, 'BA':184.76}
bStock = aStock
aStock.clear() # aStock和bStock均被清空

字典使用案例

# JSON格式
x = {"name":"Niuyun","address":{"city":"Beijing","street":"Chaoyang Road"}}
x['address']['street'] # 'Chaoyang Road'
# 搜索引擎关键字查询
# Bing中国 http://cn.bing.com/search?q=%us
import requests
kw = {'q':'Python dict'}
r.request.get('http://cn.bing.com/search',params=kw)
r.url
print(r.text)
# 可变长关键字参数
def foo(args1, *argst, **argsd):
print(args1)
print(argst)
print(argsd)
foo('Hello,', 'Wangdachui', 'Niuyun', 'Linling', a1=1, a2=2, a3=3)
# Hello,
# ('Wangdachui', 'Niuyun', 'Linling')
# {'a1':1, 'a3':3, 'a2':2}

集合

# 解决姓名重复
names = ['Wangdachui','Niuyun','Wangzi','Wangdachui','Linling','Niuyun']
namesSet = set(names)
namesSet # {'Wangdachui', 'Wangzi', 'Linling', 'Niuyun'}

集合包括可变集合(set)和不可变集合(frozenset)

aSet = set('hello') # {'o', 'h', 'e', 'l'}
bSet = frozenset('hello') # frozenset({'o', 'h', 'e', 'l'})

集合关系运算

aSet = set('sunrise')
bSet = set('sunset')
aSet & bSet # {'u', 'n', 's', 'e'} 取交集
aSet | bSet # {'u', 'e', 't', 'r', 's', 'i', 'n'} 取并集
aSet - bSet # {'r', 'i'} 属于aSet,不属于bSet
aSet ^ bSet # {'t', 'r', 'i'} 对称差分,单独属于某个集合的
# 上面的操作也可以通过函数完成
aSet.issubset(bSet) # False
aSet.intersection(bSet) # {'u', 'n', 's', 'e'}
aSet.difference(bSet) # {'r', 'i'}
cSet = aSet.copy()
cSet # {'s', 'r', 'e', 'i', 'u', 'n'}
# 对于可变集合
aSet = set('sunrise')
aSet.add('!')
aSet.remove('!')
aSet.update('Yeah')
aSet.clear()

remove(x)如果元素x不存在会引发KeyError,discard(x)也是删除元素x,如果存在此元素则删除,不存在不会报异常。

扩展库Scipy

包括Numpy、Scipy library、Matplotlib、IPython、Sympy、pandas六个核心库。主要为数学、科学和工程服务。

ndarray

维度(dimensions)称为轴(axis),轴的个数称为秩(rank)。

ndarray的基本属性

  • ndarray.ndim 秩
  • ndarray.shape 维度
  • ndarray.size 元素总个数
  • ndarray.dtype 元素类型
  • ndarray.itemsize 元素字节大小
import numpy as np
aArray = np.array([1,2,3])
# array([1, 2, 3])
bArray = np.array([(1,2,3),(4,5,6)])
# array([[1, 2, 3],
# [4, 5, 6]])
np.arange(1,5,0.5)
# array([ 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5])
np.random.random((2,2))
# array([[ 0.31768718, 0.88613606],
# [ 0.73385623, 0.13773246]])
np.linspace(1,2,10,endpoint=False) # endpoint默认为True
# array([ 1. , 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9])
np.ones([2,3])
# array([[ 1., 1., 1.],
# [ 1., 1., 1.]])
np.zeros((2,2))
# array([[ 0., 0.],
# [ 0., 0.]])
np.fromfunction(lambda i,j:(i+1)*(j+1),(9,9))
# array([[ 1., 2., 3., 4., 5., 6., 7., 8., 9.],
# [ 2., 4., 6., 8., 10., 12., 14., 16., 18.],
# [ 3., 6., 9., 12., 15., 18., 21., 24., 27.],
# [ 4., 8., 12., 16., 20., 24., 28., 32., 36.],
# [ 5., 10., 15., 20., 25., 30., 35., 40., 45.],
# [ 6., 12., 18., 24., 30., 36., 42., 48., 54.],
# [ 7., 14., 21., 28., 35., 42., 49., 56., 63.],
# [ 8., 16., 24., 32., 40., 48., 56., 64., 72.],
# [ 9., 18., 27., 36., 45., 54., 63., 72., 81.]])
print(bArray[0:2])
# [[1 2 3]
# [4 5 6]]
print(bArray[:,[0,1]])
# [[1 2]
# [4 5]]
print(bArray[1,[0,1]])
# [4 5]
for row in bArray:
print(row)
# [1 2 3]
# [4 5 6]
# ndarray的操作
aArray = np.array([(1,2,3),(4,5,6)])
aArray.shape
# (2,3)
bArray = aArray.reshape(3,2)
bArray
# array([[1, 2],
# [3, 4],
# [5, 6]])
aArray
# array([[1, 2, 3],
# [4, 5, 6]])
aArray.resize(3,2)
# array([[1, 2],
# [3, 4],
# [5, 6]])
bArray = np.array([1,3,7])
cArray = np.array([3,5,8])
np.vstack((bArray,cArray)) # 垂直方向拼接
# array([[1, 3, 7],
# [3, 5, 8]])
np.hstack((bArray,cArray)) # 水平方向拼接
# array([1, 3, 7, 3, 5, 8])
# ndarray的计算
aArray = np.array([(5,5,5),(5,5,5)])
bArray = np.array([(2,2,2),(2,2,2)])
cArray = aArray * bArray
cArray
# array([[10, 10, 10],
# [10, 10, 10]])
aArray += bArray
aArray
# array([[7, 7, 7],
# [7, 7, 7]])
a = np.array([1,2,3])
b = np.array([[1,2,3],[4,5,6]])
a + b
# array([[2, 4, 6],
# [5, 7, 9]])
aArray = np.array([(1,2,3),(4,5,6)])
aArray.sum()
# 21
aArray.sum(axis=0)
# array([5,7,9])
aArray.sum(axis=1)
# array([ 6,15])
aArray.min() # return value
# 1
aArray.argmax(5) # return index
# 5
aArray.mean() # avg
# 3.5
aArray.var() # 方差
# 2.9166666666666665
aArray.std() # 标准差
# 1.707825127659933
# ndarray的专门应用——线性代数
x = np.array([[1,2],[3,4]])
r1 = np.linalg.det(x) # 行列式
r2 = np.linalg.inv(x) # 逆矩阵
r3 = np.dot(x,x) # 矩阵内积

ufunc函数是一种能对数组的每个元素进行操作的函数。NumPy内置的许多函数都是在C语言级别实现的,计算速度非常快。

import time
import math
import numpy as np
x = np.arange(0,100,0.01)
t_m1 = time.clock()
for i,t in enumerate(x):
x[i] = math.pow((math.sin(t)),2)
t_m2 = time.clock()
y = np.arange(0,100,0.01)
t_n1 = time.clock()
y = np.power(np.sin(y),2)
t_n2 = time.clock()
print('Runing time of math:', t_m2 - t_m1)
print('Runing time of numpy:', t_n2 - t_n1)
# Runing time of math: 0.006558000000000064
# Runing time of numpy: 0.000580000000000247

变长字典Series

类似一维数组的对象,由数据和索引组成

from pandas import Series
import pandas as pd
import numpy as np
aSer = pd.Series([1,2.0,'a'])
aSer
# 0 1
# 1 2
# 2 a
# dtype: object
bSer = pd.Series(['apple','peach','lemon'],index=[1,2,3])
bSer
# 1 apple
# 2 peach
# 3 lemon
# dtype: object
bSer.index
# Int64Index([1, 2, 3], dtype='int64')
bSer.values
# array(['apple', 'peach', 'lemon'], dtype=object)
aSer = Series([3,5,7],index=['a','b','c'])
aSer['b']
# 5
aSer * 2
# a 6
# b 10
# c 14
# dtype: int64
np.exp(aSer)
# a 20.085537
# b 148.413159
# c 1096.633158
# dtype: float64
# Series的数据对齐
data = {'AXP':'86.40','CSCO':'122.64','BA':'99.44'}
sindex = ['AXP','CSCO','BA','AAPL']
aSer = pd.Series(data, index = sindex)
aSer
# AXP 86.40
# CSCO 122.64
# BA 99.44
# AAPL NaN
# dtype: object
pd.isnull(aSer)
# AXP False
# CSCO False
# BA False
# AAPL True
# dtype: bool
bSer = {'AXP':'86.40','CSCO':'122.64','CVX':'23.78'}
cSer = pd.Series(bSer)
aSer + cSer
# AAPL NaN
# AXP 86.4086.40
# BA NaN
# CSCO 122.64122.64
# CVX NaN
# dtype: object

Series的name属性

data = {'AXP':'86.40','CSCO':'122.64','BA':'99.44'}
sindex = ['AXP','CSCO','BA','AAPL']
aSer = pd.Series(data, index = sindex)
aSer.name = 'cnames'
aSer.index.name = 'volume' # 类似excel中的字段名
aSer
# volume
# AXP 86.40
# CSCO 122.64
# BA 99.44
# AAPL NaN
# Name: cnames, dtype: object

DataFrame

是一个表格型的数据结构,含有一组有序的列(类似于index),大致可看成共享同一个index的Series集合。

import pandas as pd
import numpy as np
data = {'name':['Wangdachui','Linling','Niuyun'],'pay':[4000,5000,6000]}
frame = pd.DataFrame(data)
frame
# name pay
# 0 Wangdachui 4000
# 1 Linling 5000
# 2 Niuyun 6000
data = np.array([('Wangdachui',4000),('Linling',5000),('Niuyun',6000)])
frame = pd.DataFrame(data, index = range(1,4), columns = ['name','pay'])
frame
# name pay
# 1 Wangdachui 4000
# 2 Linling 5000
# 3 Niuyun 6000
frame.index
# RangeIndex(start=1, stop=4, step=1)
frame.columns
# Index(['name', 'pay'], dtype='object')
frame.values
# array([['Wangdachui', '4000'],
# ['Linling', '5000'],
# ['Niuyun', '6000']], dtype=object)