一、数据结构和序列
1.1、元组:有一种固定长度,不可修改的python对象序列
tup = 1,2,3 tup : (1,2,3)
tup = tuple([4,0,2]) tup : (4,0,2)
tup[0] = 4
元组添加元素:tup = (["foo",[1,2],True])
tup[1].append(3)
tup : ("foo",[1,2,3],True)
同样可以用 + 和 * 生成更长的元组:(1,2) + ("bar") = (1,2,"bar")
("foo","bar") * 2 = ("foo","bar","foo","bar")
元组拆包:tup = (1,2,3)
a,b,c = tup
b = 2
1.2、列表:长度可变,也可修改,使用[ ]和list函数创建
a_list= [2,3,7,None]
b = ("foo","bar","baz")
b_list = list(b)
b_list : ["foo","bar","baz"]
增加元素:b_list.append(2) b_list : ["foo","bar","baz",2]
b_list.extend(["a","b"]) b_list : ["foo","bar","baz","a","b"]
b_list.insert(1,"two") b_list : ["foo","two","bar","baz","a","b"]
删除元素:b_list.pop(3) b_list : ["foo","two","bar","a","b"]
b_list.remove("two") b_list : ["foo","bar","a","b"]
排序:sort
a = [2,3,1,5,4]
a.sort() a : [1,2,3,4,5]
b = ["as","swa","smaill","c","six"]
b.sort(key = len) b : ["c","as","swa","six","smaill"]
1.3、内建序列函数
enumerate:同时返回(i,value)元组的序列,i是元素的索引 ,value是元素的值
list = ["foo","bar","baz"]
mapping = { }
for i , value in enumerate(list):
mapping[value] = i
mapping : {"foo":0,"bar":1,"baz":2}
sorted:返回一个根据任意序列中的元素新建的已排序列表
sorted([7,3,5,1])
[1,3,5,7]
sorted(mapping.items(), key = lammbda x : x[1],reverse = True)
{"baz":2,"bar":1,"foo":0}
zip:将列表、元组、或其他元素配对,新建一个元组构成的列表
a = ["foo","bar","baz"]
b = ["one","two","three"]
配对:zipped = zip(a,b)
list(zipped) = [("foo","one"),("bar","two"),("baz","three")]
拆分:firstname , lastname = zip(*list(zipped))
firstname : ("foo","bar","baz")
lastname : ("one","two","three")
reversed:函数将序列的元素倒序排列
list(reversed(range(10)))
[9,8,7,6,5,4,3,2,1,0]
1.4、字典:字典的键不能重复
data = {"a":"some value","b":[1,2,3,4],"c":"an integer"}
字典删除:data.pop("b") data : {"a":"some value","c":"an integer"}
del data[0] data : {"c":"an integer"}
将两个字典合并:data.update({"d":12,"e":"foo"})
{"c":"an integer","d":12,"e":"foo"}
从序列生成字典:mapping = dict(zip(range(5),reversed(range(5))))
mapping : {0:4,1:3,2:2,3:1,4:0}
字典取值(默认值):value = some_dict.get(key,default_value) 没有值时返回default_value
data.keys() 取键;data.values() 取值;data.items() 同时取
一个常见的场景为字典中的值集合通过设置,成为另一种集合
words = ["apple","bat","bar","stom","book"]
by_letter = {}
for word in words:
letter = word[0]
if letter not in by_letter:
by_letter[letter] = [word]
else:
by_letter[letter].append(word)
by_letter:{"a":["apple"],"b":["bat","bar","book"],"s":["stom"]}
上述代码可替换为:
by_letter = {}
for word in words:
letter = word[0]
by_letter.setdefault(letter,[]).append(word)
1.5、集合:一种无序且元素唯一的容器,通过set或者大括号创建
set([1,1,2,3,4]) {1,2,3,4}
{1,1,2,3,3,4} {1,2,3,4}
1.6、列表、集合和字典的推导式
1.6.1 列表:
[expr for val in collection if condition]
等价于
result = []
for val in collection:
if condition
result.append(expr)
例:string = ["a","as","bat","car","dove","python"]
[x.upper() for x in string if len(x) > 2]
["BAT","CAR","DOVE","PYTHON"]
1.6.2 集合:集合推导式和列表一样,只需把中括号换成大括号
{expr foe val in collection if condition}
例:string = ["a","as","bat","car","dove","python"]
unique = {len(x) for x in string}
{1,2,3,4,6}
1.6.3 字典
{key_expr :value_expr for value in collection if condition}
例:string = ["a","as","bat","car","dove","python"]
{val : index for index , val in enumerate(string)}
{"a":0,"as":1,"bat":2,"car":3,"dove":4,"python":5}
1.6.4 嵌套列表推导式
all_data = [["john","emily","mary"],["maria","juan","natalis"]]
[name for names in all_data for name in names if name.count("a") >= 2]
["maria","natalis"]
或者:[[name for name in names if name.count("a") >=2] for names in all_data]
二、Numpy
生成一个数组:data = np.array([[-0.2,0.4,-0.5],
[0.6,0.99,0.3]])
随机生成一个数组:data = np.random.randn(2,3)
[[-0.2,0.4,-0.5],
[0.6,0.99,0.3]]
查看数组维度:data.ndim 2
查看数组属性:data.shape (2,3)
查看数组类型:data.dtype dtype("float64")
数组生成函数
arange python内建函数range的数组版,返回一个数组
ones 根据给定形状和数据类型生成全1数组
ones_like 根据给定的数组生成一个形状一样的全1数组
zeros 根据给定形状和数据类型生成全0数组
zeros_like 根据给定的数组生成一个形状一样的全0数组
empty 根据给定形状生成一个没有初始化数值的空数组
empty_like 跟据给定的数组生成一个形状一样但没有初始化数值的空数组
full 根据给定的形态和数据类型生成指定数值的数组
full_like 根据所给定的数组生成一个形态一样但内容是指定数值的数组
astype 显示的转换数组的数据类型
arr = np.array([1,2,3,4,5])
arr.dtype dtype("int64")
float_arr = arr.astype(np.float64)
flaot_arr.dtype dtype("float64")
如果想要一份数组切片的拷贝而不是一份视图的话,就必须显示的负责这个数组,例如arr[5:8].copy()
布尔索引
names = np.array(["bob","joe","will","bob"])
data =np.random.randn(4,4)
data
[[0.1,0.3,0.2,-0.8],
[0.4,-0.2,0.5,0.1],
[0.1,0.9,0.5,-0.4],
[0.5,0.3,-0,2,0.3]]
data[names == "bob"]
[[0.1,0.3,0.2,-0.8],
[0.5,0.3,-0,2,0.3]]
data[names == "bob",2:]
[[0.2,-0.8],
[-0.2,0.3]]
取反时在表达式前面加上~
data[~(names == "bob")]
[[0.4,-0.2,0.5,0.1],
[0.1,0.9,0.5,-0.4]]
当多个名字时,可以对多个布尔值条件进行联合,需要使用数字操作,&(and)和|(or)
如:mask = (names == "bob") | (names == "joe")
data[mask];或者data[names.isin(["bob","joe"])]
data[data < 0] = 0 将 < 0 的数值替换为0
数组的转置:data.T
一元数组通用函数
例:np.sqrt(data)
函数名 描述
abs,fabs 计算每个元素的绝对值
sqrt 计算每个元素的平方根(等价于data ** 0.5)
square 计算每个元素的平方(等价于data ** 2)
exp 计算每个元素的自然指数e
log,log10,log2,log1p 分别对应:自然对数(e为底),10为底,2为底,log(1+x)
rint 将元素保留到整数位,并保持dtype
isnan 返回数组中的元素是否时一个NaN(不是一个数值),形式为布尔值数组
... ...
条件逻辑:np.where(cond,xarr,yarr) 类似excel中的if语句
数学和统计方法
data.sum()或np.sum(data)
方法 描述
sum 沿轴向计算所有元素的累和
mean 数学平均,0长度的数组平均值为NaN
std,var 标准差和方差
min,max 最小值和最大值
argmin,argmax 最小值和最大值的位置
cumsum 从0开始元素累计和
cumprod 从1开始元素累计积
布尔值数组
arr = np.random.randn(100)
(arr > 0).sum() #正值的个数
42
any检查数组中是否至少有一个True,而all检查是否每个值都是True
bools = np.array([Flase,Flase,True,Flase])
bools.any() True
bools.all() Flase
唯一值与其他集合逻辑
np.unique:唯一
names = np.array(["a","b","b","c"])
np.unique(names) ["a","b","c"]
np.in1d:检查一个数组中的值是否在另外一个数组中,并返回布尔值
arr = np.array([1,2,3])
np.in1d(arr,[1,2]) [True,True,Flase]
方法 描述
unique(x) 计算x的唯一值,并排序
intersectid(x,y) 计算x和y的交集 x|y
union1d(x,y) 计算x和y的并集 x&y
in1d(x,y) 计算x的元素是否在y中,并返回布尔值
setdiff1d(x,y) 计算在x但不在y中的元素
setxor1d(x,y) 异域集,在x中或在y中,但不属于x、y交集的元素
示例:生成一个随机漫步
import random
start = 0
walk = [start]
n = 1000
for i in range(n):
step = 1 if random.randint(0,1) else -1
start += step
walk.append(start)
三、Pandas
DataFrame的创建
data = pd.DataFrame(data,index = [],columns = [])
使用isnull和notnull函数来检查缺失数据
obj = pd.Series({"a":np.nan,"b":1200,"c":1400})
obj
a NaN
b 1200
c 1400
pd.isnull(obj) 或obj.isnull()
a True
b Flase
c Flase
notnull则相反
删除创建的列
del data["列名"] 或者 data.drop("列名" , axis = 1)
从DataFrame中选取的列时数据的视图,而不是拷贝,因此对Series的修改会映射到DataFrame中,如果需要复制,则应当使用显示的copy方法。
3.1 重建索引reindex
reindex 是pandas的重要方法,该方法用于创建一个符合新索引的新对象,并按新索引进行排列,如果某个索引值之前并不存在,则会引入缺失值。methon允许我们使用ffill(向前填充)bfill(向后填充);也适应于columns。
obj = pd.Series([4,7,-5,3],index = ["d","b","a","c"])
d 4
b 7
a -5
c 3
obj1 = obj.reindex(index = ["a","b","c","d","e"])
a -5
b 7
c 3
d 4
e NaN
obj2 = obj.reindex(index = ["a","b","c","d","e"],methon = "ffill")
a -5
b 7
c 3
d 4
e 4
reindex方法的参数
参数 描述
index/columns 新建作为索引的序列,可以是索引实例或任意其他序列型Python数据结构
methon 插值方式,“ffill”为向前填充,“bfill”为向后填充
fill_value 通过重新索引引入缺失数据时使用的替换值
limit 当向前或向后填充时,所需要填充的最大尺寸间隙
tolerance 当向前或向后填充时,所需要填充的不精准匹配下的最大尺寸间隙
level 匹配MultiIndex级别的简单索引,否则选择子集
copy 数据复制
3.2 轴向上删除条目 drop
data.drop(["A","B"]) 默认删除行
data.drop(["A","B"],axis = 1) 删除列
inplace = True 直接操作原对象而不返回新对象
3.3索引、选择、过滤
data = pd.DataFrame(np.range(16).reshape((4,4)),
index = ["A","B","C","D"],
columns = ["one","two","three","four"])
data
one two three four
A 0 1 2 3
B 4 5 6 7
C 8 9 10 11
D 12 13 14 15
data[["two","three"]]
two three
A 1 2
B 5 6
C 9 10
D 13 14
data[:2]
one two three four
A 0 1 2 3
B 4 5 6 7
data[data["three"] > 5]
one two three four
B 4 5 6 7
C 8 9 10 11
D 12 13 14 15
data[(data["three"] > 5) & (data["three"] < 12)]
one two three four
B 4 5 6 7
C 8 9 10 11
data[data < 5] = 0
one two three four
A 0 0 0 0
B 0 5 6 7
C 8 9 10 11
D 12 13 14 15
3.3.1 使用 loc (轴标签)和 iloc(整数标签) 选择数据,取子集
data.loc[["B","C"],["two","three"]]
data.iloc[[1,2],[1,2]]
two three
B 5 6
C 9 10
data.iloc[:,:3][data.three > 5]
data[data < 5] = 0
one two three
B 0 5 6
C 8 9 10
D 12 13 14
多层次筛选
df.loc[('A',slice(None)),:]
DataFrame索引选项
类型 描述
df[val] 从DataFrame中选择单列或列序列
df.loc[val] 根据标签选择DataFrame中选择单行或多行
df.loc[:,val] 根据标签选择DataFrame中选择单列或多列
df.loc[val1,val2] 根据标签同时选择行和列的一部分
df.iloc[where] 根据整数位置选择DataFrame中选择单行或多行
df.iloc[:,where] 根据整数位置选择DataFrame中选择单列或多列
df.iloc[where1,where2] 根据整数位置同时选择行和列的一部分
df.at[label1,label2] 根据行列标签选择单个标量值,同loc等价
df.iat[label1,label2] 根据行列整数位置选择单个标量值,同iloc等价
reindex 通过标签选择行或列
get_value,set_value 根据行和列的标签设置单个值
多重索引取子集
data1 data2
key1 key2
a one 0.041290 -2.561272
two 1.640716 -0.752232
b one -1.058453 0.469520
two 0.911080 -0.158005
df.loc[(slice(None),"one"),:]
data1 data2
key1 key2
a one 0.041290 -2.561272
b one -1.058453 0.469520
df.loc[("a",),:]
data1 data2
key1 key2
a one 0.041290 -2.561272
two 1.640716 -0.752232
3.3.2 算术和数据对齐
将两个列表进行简单算术运算,会自动进行数据对齐,没有相同行列的值会计算为空值
df1 = pd.DataFrame({"A":[1,2,3],"B":[2,3,4]})
df2 = pd.DataFrame({"A":[3,3,3]})
df1 df2 df1+df2
A B A A B
1 2 3 5 NaN
2 3 3 6 NaN
3 4 3 7 NaN
使用填充值的算术方法
df1.add(df2,fill_values = 0)
A B
5 2
6 3
7 4
df1.rdiv(1) 等价于 1/df1
df2.reindex(columns = df1.columns,fill_value = 0)
df2
A B
3 0
3 0
3 0
灵活算术方法
方法 描述
add,radd 加法(+)
sub,rsub 减法(-)
div,rdiv 除法(/)
floordiv,rfloordiv 整除(//)
mul,rmul 乘法(*)
pow,rpow 幂次方(**)
备注:r则是翻转过来
DataFrame和Series的数据运算
df
A B
0 1 2
1 2 3
2 3 4
df - df.loc[0] df.sub(df["a"],axis = "index")
A B A B
0 0 0 0 0 1
1 1 1 1 0 1
2 2 2 2 0 1
3.3.3 函数应用和映射:
将函数应用到一行或一列的一维数组上,DataFrame的apply方法可实现这个功能,如果传递axis = "columns"给apply函数,函数将被每一行调用一次。如果想要作用于每个元素,可用applymap 或Serise的map方法。
3.3.4 排序和排名:
排序:如果需要按行或按列索引进行排序则用sort_index,该方法返回一个新的排好序的对象,数据默认进行升序排列,ascending = Flase 进行降序排列。
data = pd.DataFrame(np.arange(8).reshape((2,4)),index = ["three","one"],columns = ["d","a","b","c"])
data.sort_index()
d a b c
one 4 5 6 7
three 0 1 2 3
data.sort_index(axis = 1)
a b c d
three 1 2 3 0
one 5 6 7 4
如果对值进行排列,则使用sort_values方法。默认情况下缺失值会被排序至底部。
data = pd.DataFrame("b":[4,7,-3,2],"a":[0,1,0,1])
a b
0 0 4
1 1 7
2 0 -3
3 1 2
data.sott_values(by = ["a","b"])
a b
2 0 -3
0 0 4
3 1 2
1 1 7
排名:是指对数组从1到有效数据点总数分配名次的操作。数据默认进行升序排列,ascending = Flase 进行降序排列。
data = pd.Series([7,-5,7,4,2,0,4])
data.rank(method = "first")
0 6
1 1
2 7
3 4
4 3
5 2
6 5
也可以添加axis = "columns"进行横向排序
排名中平级关系打破方法
方法 描述
average 默认:在每组中分配平均
min 对整个数组使用最小排名
max 对整个数组使用最大排名
first 按照值在数据中出现的次序分配排名
dense 类似min,但组间排名总是增加1,而不是一个数组中的相等元素数量
3.4 描述性统计的概述与计算
DataFrame 进行描述性统计时默认对列进行计算,传入axis = 1或者“columns”则会将一行上各个列的值进行运算。除非整个切片上(行或者列)都是NA,否则NA值会自动排除,可以通过禁用skipna来实现不排除NA值。
describe 一次产生多个汇总统计。
方法 描述
count 非NA值的个数
describe 计算各列的汇总统计集合
min,max 计算最小值,最大值
argmin,argmax 分别计算最小值、最大值所在的索引位置
idxmin,idxmax 分别计算最小值、最大值所在的索引标签
quantile 计算样本的从0到1间的分位数
sum 加和
mean 均值
median 中位数
mad 平均值的平均绝对偏差
prod 所有值的积
var 值的样本方差
std 值的样本标准差
skew 样本偏度值
kurt 样本峰度值
cumsum 累计值
cummin,cummax 累计值的最小值和累计值的最大值
comprod 值的累计积
diff 计算第一个算术差值(对是时间序列有用)
pct_change 计算百分比
corr 相关性
cov 协方差
3.4.1 唯一值、计数和成员属性
唯一值:函数uniques = data.a.unique(),如果需要可进行排序(uniques.sort( ))
计数:value_counts,默认是降序排列,sort = Flase取消排序
isin执行向量化的成员属性检查
obj = pd.Series(["c","a","d","a","b"])
0 c
1 a
2 d
3 a
4 b
obj.isin(["b","c"])
0 True
1 Flase
2 Flase
3 Flase
4 True
obj[obj.isin(["b","c"])]
0 c
4 b
取反,前面加“~”
obj[~obj.isin(["b","c"])]
1 a
2 d
3 a
例子
data = pd.DataFrame({"Q1":[1,3,4,3,4],
"Q2":[2,3,1,2,3],
"Q3":[1,5,2,4,4]})
result = data.apply(pd.value_counts).fillna(0)
Q1 Q2 Q3
1 1 1 1
2 0 2 1
3 2 2 0
4 2 0 2
5 0 0 1
四、数据清洗与准备
4.1 处理缺失值
函数名 描述
dropna 根据每个标签的值是否是缺失值来筛选轴标签,并根据允许丢失的数据量来确定阈值
fillna 用某些值填充缺失的数据或使用插值方法(如ffill或bfill)
isnull 返回表明哪些值是缺失值的布尔值
notnull isnull的反函数
4.1.1 过滤缺失值dropna
默认情况下是删除包含缺失值的行
data = pd.DataFrame([[1,6.5,3],[1,np.nan,np.nan],[np.nan,np.nan,np.nan],[np.nan,6,5,3]])
0 1 2
0 1 6.5 3
1 1 NaN NaN
2 NaN NaN NaN
3 NaN 6.5 3
data.dropna()
0 1 2
0 1 6.5 3
传入how = all时,删除所有值为NaN的行
data.dropna(how = "all")
0 1 2
0 1 6.5 3
1 1 NaN NaN
3 NaN 6.5 3
如果要用同样的方法删除列,传入参数axis = 1
data[4] = np.nan
0 1 2 3
0 1 6.5 3 NaN
1 1 NaN NaN NaN
2 NaN NaN NaN NaN
3 NaN 6.5 3 NaN
data.dropna(how = "all",axis = 1)
0 1 2
0 1 6.5 3
1 1 NaN NaN
2 NaN NaN NaN
3 NaN 6.5 3
如果想保留包含一定数量的观察值的行,可以用thresh参数来表示
df = pd.DataFrame(np.arange(21).reshape((7,3)))
df.iloc[:4,1] = np.nan
df.iloc[:2,2] = np.nan
0 1 2
0 0 NaN NaN
1 3 NaN NaN
2 6 NaN 8
3 9 NaN 11
4 12 13 14
5 15 16 17
6 18 19 20
df.dropna(thresh = 2)
2 6 NaN 8
3 9 NaN 11
4 12 13 14
5 15 16 17
6 18 19 20
4.1.2 补全缺失值 fillna
df.fillna(0)
0 1 2
0 0 0 0
1 3 0 0
2 6 0 8
3 9 0 11
4 12 13 14
5 15 16 17
6 18 19 20
df.fillna({1:0.5,2:0}) #也可以使用均值、中位数等填充df[1].mean()
0 1 2
0 0 0.5 0
1 3 0.5 0
2 6 0.5 8
3 9 0.5 11
4 12 13 14
5 15 16 17
6 18 19 20
df.fillna(methon = 'bfill')
0 1 2
0 0 13 8
1 3 13 8
2 6 13 8
3 9 13 11
4 12 13 14
5 15 16 17
6 18 19 20
df.fillna(methon = 'bfill',limit = 2)
0 1 2
0 0 NaN 8
1 3 NaN 8
2 6 13 8
3 9 13 11
4 12 13 14
5 15 16 17
6 18 19 20
fillna的参数
参数 描述
value 标量值或字典型对象用于填充缺失值
methon 插值方法,如果没有其他参数,默认是'ffill'
axis 需要填充的轴,默认是axis = 0
inplace 修改被调用的对象,而不是生成一个备份
limit 用于向前或向后填充时最大的填充范围
4.2 数据转换
4.2.1 删除重复值 drop_duplicates()
data = pd.DataFrame({"k1":["one","two"] * 3 + ["two"],"k2":[1,1,2,3,3,4,4]})
k1 k2
0 one 1
1 two 1
2 one 2
3 two 3
4 one 3
5 two 4
6 two 4
DataFrame 的duplicated 方法返回一个布尔值Series,反应的是每一行是否存在重复情况
data.duplicated()
0 Flase
1 Flase
2 Flase
3 Flase
4 Flase
5 Flase
6 True
duplicates对重复部分进行删除,返回一个DataFrame
data.drop_duplicates()
k1 k2
0 one 1
1 two 1
2 one 2
3 two 3
4 one 3
5 two 4
data.drop_duplicates(["k1"])
k1 k2
0 one 1
1 two 1
data.drop_duplicates(["k1","k2"],keep = "last")
k1 k2
0 one 1
1 two 1
2 one 2
3 two 3
4 one 3
6 two 4
4.2.2 使用函数或映射进行数据转换:map apply
data = pd.DataFrame({"food":["bacon","pulled pork","bacon","pastrami"],"ounces":[4,3,12,6]})
ma = {"bacon":"pig","pulled pork":"pig","pastrami":"cow"}
data
food ounces
0 bacon 4
1 pulled pork 3
2 bacon 12
3 pastrami 6
data["a"] = data["food"].apply(lambda x:ma[x])
data["a"] = data["food"].map(ma)
data["a"] = data["food"].map(lambda x:ma[x])
food ounces a
0 bacon 4 pig
1 pulled pork 3 pig
2 bacon 12 pig
3 pastrami 6 cow
4.2.3 替换值 replace
data = pd.Series([1,-999,2,-999,1000,3])
0 1
1 -999
2 2
3 -999
4 1000
5 3
data.replace(-999,np.nan)
0 1
1 NaN
2 2
3 NaN
4 1000
5 3
data.replace([-999,1000],np.nan)#一次替换多个值
0 1
1 NaN
2 2
3 NaN
4 NaN
5 3
data.replace([-999,1000],[np.nan,0])#不同的值替换不同的值
data.replace({-999:np.nan,1000:0})字典形式替换
0 1
1 NaN
2 2
3 NaN
4 0
5 3
4.2.4从命名轴索引 rename
data = pd.DataFrame(np.range(12).reshape((3,4)),
index = ["Ohio","Colo","New"],
columns = ['one','two','three','four'])
one two three four
Ohio 0 1 2 3
Colo 4 5 6 7
New 8 9 10 11
data.rename(index = str.lower,columns = str.upper)
ONE TWO THREE FOUR
ohio 0 1 2 3
colo 4 5 6 7
new 8 9 10 11
data.rename(index = {"ohio":"haha"},columns = {"ONE":"one"})
one TWO THREE FOUR
haha 0 1 2 3
colo 4 5 6 7
new 8 9 10 11
如果想要修改原有数据集,传入replace = True
4.2.5 离散化和分箱 cut 和qcut
连续值经常需要离散化或分箱进行分析
ages =[22,20,20,27,21,23,37,31,61,45,41,32]
需要将上述按18-25、26-35、36-60及60以上进行分组
bins = [18,25,35,60,100]
cats = pd.cut(ages,bins)
cats
[(18,25],(18,25],(18,25],(26,35],(18,25],(18,25],(36,60],(26,35],(60,100],(36,60],(36,60],(26,35]]
pd.value_counts(cats)
(18,25] 5
(25,35] 3
(36,60] 3
(60,100] 1
默认情况下分箱是左开右闭,( ],可以传递right = Flase 来修改哪一边封闭。
也可以传入labels选项来定义箱体名
names = ["youth","youthadult","middleaged","senior"]
cuts = pd.cut(ages,bins,labels = names)
[youth,youth,youth,youthadult,youthyouth,middleaged,youthadult,senior,middleaged,middleaged,youthadult]
如果传递给cut整数个箱来代替显示的箱边,pandsas会根据数据中的最大值和最小值计算出等长的箱(等宽分箱)。
data = pd.ranom.rand(20)
pd.cut(data,4,precision = 2)
[(0.34,0.55],(0.34,0.55],(0.76,0.97],(0.12,0.34],(0.55,0.76],(0.12,0.34]......]
#precision = 2 设置精度,保留2为小数
qcut,则基于样本分为数进行分箱,获得等长的箱(等深分箱)
data = pd.random.randon(1000)
cats = pd.qcut(data,4)
[(-0.0265,0.62],(0.62,3.928],(-0.68,-0.0265].........]
pd.value_counts(cats)
(0.62,3.928] 250
(-0.0265,0.62] 250
(-0.68,-0.0265] 250
(-2.95,-0.68] 250
与cut类似,qcut也可以传入自定义的分位数(0和1之间的数据)
pd.qcut(data,[0,0.1,0.5,0.9,1])
4.2.6 随机抽样
data = pd.DataFrame(np.arange(20).reshape((5,4)))
data
0 1 2 3
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
3 12 13 14 15
4 16 17 18 19
data.sample(3) 随机不重复抽取
0 1 2 3
3 12 13 14 15
4 16 17 18 19
2 8 9 10 11
如果允许重复抽样,传入replace = True参数
data.sample(3,replace = True) 随机重复抽取
0 1 2 3
3 12 13 14 15
4 16 17 18 19
3 12 13 14 15
4.2.7 计算指标/虚拟变量(哑变量)get_dummies
如果DataFrame中的一列有K个不同的值,可以衍生一个K列的值为0和1的矩阵或DataFrame.
df = pa.DataFrame({"key":["b","b","a","c","a","b"],"data1":range(6)})
pd.get_dummies(df["key"])
a b c
0 0 1 0
1 0 1 0
2 1 0 0
3 0 0 1
4 1 0 0
5 0 1 0
如果想在生成的列名前加入前缀,传入prefix = " "设置
dummies = pd.get_dummies(df["key"],prefix = "key")
data = df[["data1"]].join(jummies)
data1 key_a key_b key_c
0 0 0 1 0
1 1 0 1 0
2 2 1 0 0
3 3 0 0 1
4 4 1 0 0
5 5 0 1 0
如果DataFrame中的一行属于多个类型,则情况略显复杂
movies
movie_id title genres
0 1 toy story(1995) animation|children's|comedy
1 2 jumanji(1995) adventure|children's|fantasy
2 3 grumpier old men(1995) comedy|romance
3 4 waiting to exhale(1995) comedy|drama
4 5 father of the bride part 2(1995) comedy
5 6 heat(1995) action|crime|thriller
6 7 sabrina(1995) comedy|romance
7 8 tom and huck(1995) adventure|children's
8 9 sudden death(1995) action
9 10 goldeneye(1995) action|adventure|thriller
为每个电影流派添加指标变量
1.先提取所有的电影流派
all_genres = []
for i in movies.genres:
all_genres.extend(i.split("|"))
genres = pd.unique(all_genres)
2.生成一个电影流派矩阵
dummies = pd.DataFrame(np.zeros((len(movies),len(genres))),columns = genres)
3.完成电影流派指标
for i , movie in enumerate(movies.genres):
indices = dummies.columns.get_indexer(movie.split("|"))
dummies.iloc[i,indices] = 1
4.3 字符串操作,python内建字符串用法
方法 描述
count 返回子字符串在字符串中的非重叠出现次数
endwith 如果字符串以后缀结尾则返回True
startwith 如果字符串以前缀结尾则返回True
join 使用字符串作为间隔符,用于粘合其他字符串的序列 "".join(a)
index 如果在字符串中找到,则返回子字符串中第一个字符的位置,没找到则返回一个错误
find 如果在字符串中找到,则返回第一个出现子字符的第一个字符的位置,没找到则返回-1
rfind 如果在字符串中找到,则返回最后一次出现子字符的第一个字符的位置,没找到则返回-1
replace 使用一个字符串替换另外一个字符串
strip,rstrip,lstrip 修剪空白、包括换行符
split 使用分隔符将字符串分为子字符串的
lower 将大写字母替换为小写字母
upper 将小写字母替换为大写字母
tail 将首字母大写
ljust,rjust 左对齐或右对齐;用空格(或其他一些字符)填充字符串的相反侧以返回具有最小宽度的字符串
五、数据规整:连接、联合与重塑
5.1 分层索引:允许在一个轴向上拥有多个(两个或两个以上)索引层级(多个index,多个columns)。
data = pd.Series(np.arange(9),index = [["a","a","a","b","b","c","c","d","d"],
[1,2,3,1,3,1,2,2,3]])
data
a 1 0
a 2 1
a 3 2
b 1 3
b 3 4
c 1 5
c 2 6
d 2 7
d 3 8
data["b"]
b 1 3
b 3 4
data[["b":"c"]]
b 1 3
b 3 4
c 1 5
c 2 6
data.loc[["b","d"]]
b 1 3
b 3 4
d 2 7
d 3 8
在内部层级中进行索引
data.loc[:,2]
a 2 1
c 2 6
d 2 7
可以用unstack对上述data进行重新排列
data.unstack()
1 2 3
a 0 1 2
b 3 NaN 4
c 5 6 NaN
d NaN 7 8
data.unstack(0)
a b c d
1 0 3 5 NaN
2 1 NaN 6 7
3 2 4 NaN 8
unstack的反函数是stack
data.unstack().stack() 等于data
data
a 1 0
a 2 1
a 3 2
b 1 3
b 3 4
c 1 5
c 2 6
d 2 7
d 3 8
5.1.1 重排序和层级排序
有时需要重新排列轴上的层级顺序,或按特定层级的值对数据进行排序。swaplevel:返回互换级别的新对象,不改变值
data.index.names = ["key1","key2"]
data
key1 key2
a 1 0
a 2 1
a 3 2
b 1 3
b 3 4
c 1 5
c 2 6
d 2 7
d 3 8
data.swaplevel("key1","key2")
key2 key1
1 a 0
2 a 1
3 a 2
1 b 3
3 b 4
1 c 5
2 c 6
2 d 7
3 d 8
sort_index 只能在单一层级上对数据进行排序。
key1 key2
a 1 0
a 2 1
a 3 2
b 1 3
b 3 4
c 1 5
c 2 6
d 2 7
d 3 8
data.sort_index(level = 0)
a 1 0
a 2 1
a 3 2
b 1 3
b 3 4
c 1 5
c 2 6
d 2 7
d 3 8
data.sort_index(level = 1)
a 1 0
b 1 3
c 1 5
a 2 1
c 2 6
d 2 7
a 3 2
b 3 4
d 3 8
5.1.2 按层级进行汇总统计
data.sum(level = "key1")
a 3
b 7
c 11
d 15
5.1.3 set_index( )将列设置为索引层级index;reset_index将索引层级index设置为列
5.2 联合与合并数据集
5.2.1 数据库风格的DataFrame的连接:merge
left 合并操作是左边的DataFrame
right 合并操作是右边的DataFrame
how "inner","outer","left","right"之一,默认是"inner"
on 需要连接的列名,必须是在两边的DataFrame对象都有的列名,并以left和right中的列名的交集作为连接键
left_on left DataFrame 中作为连接键的列
right_on right DataFrame 中作为连接键的列
left_index 使用left的行索引所为他的连接键
right_index 使用rigth的行索引所为他的连接键
sort 通过连接键按字母顺序对合并的数据进行排序,默认是True
suffixes 在重叠情况下,添加到列名后的字符串元组,默认是("_x","_y"),合并后变为(data_x,data_y)
5.2.2 按索引合并:join
left.join(right,how = "outer",on="key")
也可以连接多个表
left.join([rigtt1,right2],how = "outer")
5.2.3 沿轴向连接:concat
s1 = pd.Series([0,1],index = ["a","b"])
s2 = pd.Series([2,3,4],index = ["c","d","e"])
s3 = pd.Series([5,6],index = ["f","g"])
pd.concat([s1,s2,s3])
a 0
b 1
c 2
d 3
e 4
f 5
g 6
pd.concat([s1,s2,s3],axis = 1)
0 1 2
a 0 NaN NaN
b 1 NaN NaN
c NaN 2 NaN
d NaN 3 NaN
e NaN 4 NaN
f NaN NaN 5
g NaN NaN 6
pd.concat([s1,s2,s3],keys = ["one","two","three"])
one a 0
b 1
two a 0
b 1
three f 5
g 6
concat 函数的参数
objs 需要连接的pandas对象列表或字典;这是备选参数
axis 连接的轴向;默认是0
join "inner","outer"
join_axes 用于设定特定索引
keys 与要连接的对象关联的值,沿着连接轴形成分层索引
ignore_index 不沿着连接轴保留索引,而产生一段新的索引
5.2.4 联合重叠数据combine_first :合并重叠部分空值时替换
a b
f NaN a 0
e 2.5 b NaN
d 0 c 2
c 3.5 d NaN
b 4.5 e NaN
a NaN f 5
b.combin_first(a)
a 0
b 4.5
c 2
d 0
e 2.5
f 5
df1 df2
a b c a b
0 1 NaN 2 0 5 NaN
1 NaN 2 6 1 4 3
2 5 NaN 10 2 NaN 4
3 NaN 6 14 3 3 6
4 7 8
df1.combin_first(df2)
a b c
0 1 NaN 2
1 4 2 6
2 5 4 10
3 3 6 14
4 7 8 NaN
5.3 重塑和透视
5.3.1 重塑 stack(堆叠)、 unstack(拆堆);互相是可逆的
data
number one two three
state
ohio 0 1 2
colo 3 4 5
result = data.stack()
state number
ohio one 0
two 1
three 2
colo one 3
two 4
three 5
result.unstack()
number one two three
state
ohio 0 1 2
colo 3 4 5
result.unstack(0) reault.unstack("state")
state ohio colo
numer
one 0 3
two 1 4
three 2 5
使用stack和unstack时可以指明需要堆叠、拆堆的名称
df
side left right
state number
ohio one 0 5
two 1 6
three 2 7
colo one 3 8
two 4 9
three 5 10
df.unstack("state")
side left right
state ohio colo ohio colo
number
one 0 3 5 8
two 1 4 6 9
three 2 5 7 10
df.unstack("state").stack("side")
state ohio colo
number side
one left 3 0
right 8 5
two left 4 1
right 9 6
three left 5 2
right 10 7
5.3.2 透视
将“长”透视为“宽”:类似于excel的数据透视表
data.pivot(行,列,值)
data
key var value
0 foo A 1
1 bar A 2
2 baz A 3
3 foo B 4
4 bar B 5
5 baz B 6
6 foo C 7
7 bar C 8
8 baz C 9
result = data.pivot("key","var","value")
key A B C
foo 1 4 7
bar 2 5 8
baz 3 6 9
将“宽”透视为“长”:透视表的反操作
result
key A B C
foo 1 4 7
bar 2 5 8
baz 3 6 9
pd.melt(result , id_vars = ["key"])
key var value
0 foo A 1
1 bar A 2
2 baz A 3
3 foo B 4
4 bar B 5
5 baz B 6
6 foo C 7
7 bar C 8
8 baz C 9
pd.melt(result , id_vars = ["key"], value_vars = ["A","B"])
key var value
0 foo A 1
1 bar A 2
2 baz A 3
3 foo B 4
4 bar B 5
5 baz B 6
pd.melt(result , value_vars = ["key","A","B"])
var value
0 key foo
1 key bar
2 key baz
3 A 1
4 A 2
5 A 3
6 B 4
7 B 5
8 B 6
六、数据聚合与分组操作 GroupBy
6.1 GroupBy机制
df
data1 data2 key1 key2
0 0 5 a one
1 1 6 a two
2 2 7 b one
3 3 8 b two
4 4 9 a one
df.groupby(["key1","key2"]).sum()
key1 key2 data1 data2
a one 4 14
two 1 6
b one 2 7
two 3 8
6.1.1 遍历各分组 (貌似不能用了)
for name , group in df.groupby(["key1"])
print("name")
print("group")
a
data1 data2 key1 key2
0 0 5 a one
1 1 6 a two
4 4 9 a one
b
data1 data2 key1 key2
2 2 7 b one
3 3 8 b two
6.1.2 选择一列或所有列的子集
df.groupby("key1")["data1"]
df.groupby("key1")[["data1"]]
等价于
df["data1"].groupby(df["key1"])
df[["data2"]].groupby(df["key1"])
如果传递的是列表或数组,则此索引操作返回的对象是分组的DataFrame,如果只有单个列名作为标量传递,即为分组的Series
df.groupby(["key1","key2"])[["data2"]].sum()
key1 key2 data2
a one 14
two 6
b one 7
two 8
6.1.3 使用字典和Series分组
people
a b c d e
joe 1 2 3 4 5
steve 6 7 8 9 10
wes 11 12 13 14 15
jim 16 17 18 19 20
travis 21 22 23 24 25
mapping = {"a":"red","b":"red","c":"blue","d":"blue","e":"red","f":""orange}
map_series = pd.Series(mapping)
people.groupby(map_series,axis = 1).sum()
people.groupby(mapping).sum()
red blue
joe 8 7
steve 23 17
wes 38 27
jim 53 37
travis 68 47
6.1.4 使用函数分组
people.groupby(len).sum()
a b c d e
3 23 26 29 32 35
5 6 7 8 9 10
6 21 22 23 24 25
key_list = ["one","one","one","two","two"]
people.groupby([len , key_list]).min()
a b c d e
3 one 1 2 3 4 5
two 16 17 18 19 20
5 one 6 7 8 9 10
6 two 21 22 23 24 25
6.1.5 根据索引层级分组
data
cty US JP
tenor 1 3 5 1 3
0 0 1 2 3 4
1 5 6 7 8 9
2 10 11 12 13 14
3 15 16 17 18 19
data.groupby(cty,axis = 1).count()
US JP
0 3 2
1 3 2
2 3 2
3 3 2
6.2 数据聚合
优化的groupby方法
函数名 描述
count 分组中非NaN的个数
sum 非NaN的和
mean 非NaN的均值
median 非NaN的算术中位数
std,var 无偏的(n-1)标准差和方差
min,max 非NaN的最小值、最大值
prod 非NaN的乘积
first,last 非NaN的第一个和最后一个值
如果要使用自己的聚合函数,需要将函数传递给aggregate或agg方法:
df
data1 data2 key1 key2
0 0 5 a one
1 1 6 a two
2 2 7 b one
3 3 8 b two
4 4 9 a one
grouped = df.groupby("key1")
def peak(arr):
return arr.max() - arr.main()
grouped.agg(peak)
data1 data2
key1
a 4 4
b 1 1
6.2.1 逐列及多函数运用
tips[:6]
total_bill tip smoker day time size tip_pct
0 16.99 1.01 No Sun Dinner 2 0.059447
1 10.34 1.66 No Sun Dinner 3 0.160542
2 21.01 3.50 No Sun Dinner 3 0.166587
3 23.68 3.31 No Sun Dinner 2 0.139780
4 24.59 3.61 No Sun Dinner 4 0.146808
5 25.25 4.71 No Sun Dinner 4 0.186240
grouped = tips.groupby(["day","smoker"])
group_pct = grouped["tip_pct"]
group_pct.agg("mean")
day smoker
Fri No 0.151650
Yes 0.174783
Sat No 0.158048
Yes 0.147909
Sun No 0.160113
Yes 0.187250
Thur No 0.160298
Yes 0.163863
如果传递的是函数或函数名的列表,则会返回这些函数名的DataFrame
group_pct.agg(["mean","std","peak"]) #peak 上面定义的函数
mean std peak
day smoker
Fri No 0.151650 0.028123 0.067349
Yes 0.174783 0.051293 0.159925
Sat No 0.158048 0.039767 0.235123
Yes 0.147909 0.061375 0.290095
Sun No 0.160113 0.042347 0.193226
Yes 0.187250 0.154134 0.644685
Thur No 0.160298 0.038774 0.193350
Yes 0.163863 0.039389 0.151240
也可以自定义列名
group_pct.agg([("foo","mean"),("bar",np.std)])
foo bar
day smoker
Fri No 0.151650 0.028123
Yes 0.174783 0.051293
Sat No 0.158048 0.039767
Yes 0.147909 0.061375
Sun No 0.160113 0.042347
Yes 0.187250 0.154134
Thur No 0.160298 0.038774
Yes 0.163863 0.039389
在DataFrame中你有更多的选项,你可以指定应用到所有列上的函数列表或每一列上要应用的不同函数。假设我们要计算tip_pct列和total_bill列的三个相同的统一值
function = ["count","mean","max"]
result = grouped(["tip_pct","total_bill"]).agg(function)
tip_pct total_bill
count mean max count mean max
day smoker
Fri No 4 0.151650 0.187735 4 18.420000 22.75
Yes 15 0.174783 0.263480 15 16.813333 40.17
Sat No 45 0.158048 0.291990 45 19.661778 48.33
Yes 42 0.147906 0.325733 42 21.276667 50.81
Sun No 57 0.160113 0.252672 57 20.506667 48.17
Yes 19 0.187250 0.710345 19 24.120000 45.35
Thur No 45 0.160298 0.266312 45 17.113111 41.19
Yes 17 0.163863 0.241255 17 19.190588 43.11
result["tip_pct"]
count mean max
day smoker
Fri No 4 0.151650 0.187735
Yes 15 0.174783 0.263480
Sat No 45 0.158048 0.291990
Yes 42 0.147906 0.325733
Sun No 57 0.160113 0.252672
Yes 19 0.187250 0.710345
Thur No 45 0.160298 0.266312
Yes 17 0.163863 0.241255
和前面一样,也可以传递具有自定义名称的元组列表
ftuples = [("Dur","mean"),("Abw",np.var)]
grouped["tip_pct","total_bill"].agg(ftuples)
tip_pct totail_bill
Dur Abw Dur Abw
day smoker
Fri No
Yes
Sat No
Yes
Sun No
Yes
Thur No
Yes
现在我们假设想要将不同的函数应用到一个或多个列上,要实现这个功能,需要将含有列名与函数对应关系的字典传递给agg
grouped.agg({"tip_pct":["min","max","mean","std"],"size":"sum"})
tip_pct size
min max mean std sum
day smoker
Fri No 0.120385 0.187735 0.151650 0.028123 9
Yes 0.103555 0.263480 0.174783 0.051293 31
Sat No 0.056797 0.291990 0.158048 0.039767 115
Yes 0.035638 0.325733 0.147906 0.061375 104
Sun No 0.059447 0.252672 0.160113 0.042347 167
Yes 0.065660 0.710345 0.187250 0.154134 49
Thur No 0.072961 0.266312 0.160298 0.038774 112
Yes 0.090014 0.241255 0.163863 0.039389 40
6.2.2 返回不含索引的聚合数据
tips.groupby(["day","smoker"],as_index = False)["tip_pct"].mean()
day smoker
0 Fri No 0.151650
1 Fri Yes 0.174783
2 Sat No 0.158048
3 Sat Yes 0.147909
4 Sun No 0.160113
5 Sun Yes 0.187250
6 Thur No 0.160298
7 Thur Yes 0.163863
6.3 通用拆分 - 应用 - 联合
假设要按组选出小费百分比最高的五组,首先要写一个特定列中最大值所在的行的函数
def top(df , n = 5 , column = "tip_pic"):
return df.sort_values(by = column)[-n:]
现在,如果我们按照smoker进行分组,调用apply函数
tips.groupby("somker").apply(top)
total_bill tip smoker day time size tip_pct
somker
No 88 24.71 5.85 No Thur Lunch 2 0.236746
185 20.69 5.00 No Sun Dinner 5 0.241663
51 7.51 2.60 No Sun Dinner 2 0.252672
149 11.61 2.00 No Thur Lunch 2 0.266312
232 14.31 3.39 No Sat Dinner 2 0.291990
Yes 109 23.17 4.00 Yes Sat Dinner 2 0.279525
183 2.07 6.50 Yes Sun Dinner 4 0.280535
67 9.60 1.00 Yes Sat Dinner 1 0.325733
178 10.29 4.00 Yes Sun Dinner 2 0.416667
172 7.25 5.15 Yes Sun Dinner 2 0.710345
top函数在DataFrame 的每个分组中被调用了一次,然后使用pandas的concat函数将结果粘贴在一起
6.3.1 压缩分组键
在前面的例子中,你可以看到所得到的对象具有分组键所形成的分层索引以及每个原始对象的索引。可以通过向groupby传递group_keys = False 来禁用这个功能
tips.groupby("somker",group_keys = False).apply(top)
total_bill tip smoker day time size tip_pct
88 24.71 5.85 No Thur Lunch 2 0.236746
185 20.69 5.00 No Sun Dinner 5 0.241663
51 7.51 2.60 No Sun Dinner 2 0.252672
149 11.61 2.00 No Thur Lunch 2 0.266312
232 14.31 3.39 No Sat Dinner 2 0.291990
109 23.17 4.00 Yes Sat Dinner 2 0.279525
183 2.07 6.50 Yes Sun Dinner 4 0.280535
67 9.60 1.00 Yes Sat Dinner 1 0.325733
178 10.29 4.00 Yes Sun Dinner 2 0.416667
172 7.25 5.15 Yes Sun Dinner 2 0.710345
6.3.2 分位数与桶分析
frame = pd.DataFrame({"data1":np.random.randn(1000),"data2":np.random.randn(1000)})
def get_stats(group):
return {"min":group.min(),"max":group.max(),"count":group.count(),"mean":group.mean()}
quartiles = pd.cut(frame.data1,4)
frame.data2.groupby(quartiles).apply(get_stats).unstack()
count max mean min
data1
(-2.956,-1.23] 95.0 1.670835 -0.039521 -3.399312
(-1.23,0.489] 598.0 3.260383 -0.002051 -2.989741
(0.489,2.208] 297.0 2.954439 0.081822 -3.745356
(2.208,3.928] 10.0 1.765640 0.024750 -1.929776
6.3.3 示例:使用指定分组值填充缺失值
data
0 0.922264
1 -2.153545
2 NaN
3 -0.375842
4 0.329939
5 NaN
6 1.105913
7 NaN
group_key = ["east"] * 4 + ["west"] * 4
fill_mean = lammbda x : x.fillna(x.mean())
data.groupby(group_key).apply(fill_mean)
0 0.922264
1 -2.153545
2 -0.535707
3 -0.375842
4 0.329939
5 0.717926
6 1.105913
7 0.717926
同样也可以为每个分组预定义一个填充值。由于每个分组都有一个内置的name属性,我们可以这样:
fill_values = {"east":0.5,"west":-1}
fill_func = lammbda x : x.fillna(fill_values[x.name])
data.groupby(group_key).apply(fill_func)
0 0.922264
1 -2.153545
2 0.5
3 -0.375842
4 0.329939
5 -1
6 1.105913
7 -1
6.3.4 加权平均值和相关性
加权平均值
df
cate data weight
0 a 1.561587 0.957515
1 a 1.219984 0.347267
2 a -0.482239 0.581362
3 a 0.315667 0.217091
4 b -0.047852 0.894406
5 b -0.454145 0.918564
6 b -0.556774 0.277825
7 b 0.253321 0.955905
get_wavg = lammbda x : np.average(x["data"],weights = x["weight"])
df.groupby("cate").apply(get_wavg)
cate
a 0.811643
b -0.122262
相关性
close_px[-4:]
AAPL MSFT XOM SPX
2011-10-11 400.29 27.00 76.27 1195.54
2011-10-12 402.19 26.96 77.16 1207.25
2011-10-13 408.43 27.18 76.37 1203.66
2011-10-14 422.00 27.27 78.11 1224.58
一个有趣的任务为:通过百分比计算各列与SPX的相关性
1.定义关联函数
spx_corr = lammbda x : x.corrwith(x.spx)
2.计算百分比变化
rets = close_px.pct_change().dropna()
3.按年对百分比变化进行分组
get_years = lambda x: x.year
by_year = rets.groupby(get_year)
4.计算相关性
by_year.apply(spx_corr)
AAPL MSFT XOM SPX
2003 0.54 0.74 0.66 1
2004 0.37 0.58 0.55 1
2005 0.46 0.56 0.63 1
2006 0.42 0.40 0.51 1
2007 0.50 0.65 0.78 1
2008 0.68 0.80 0.82 1
2009 0.70 0.65 0.79 1
也可以计算内部列的相关性,这里我们计算苹果和微软的年度相关性
by_year.apply(lambda x : x["AAPL"].corrwith(x["MSFT"]))
2003 0.48
2004 0.25
2005 0.30
2006 0.16
2007 0.41
2008 0.61
2009 0.43
6.4数据透视表与交叉表
数据透视表 pivot_table选项
选项名 描述
values 需要聚合的列名,默认情况下聚合所有数值的列
index 在结果透视表的行上进行分组的列名或者其他分组键
columns 在结果透视表的列上进行分组的列名或者其他分组键
aggfunc 聚合函数或函数列表
fill_value 在结果表中替换缺失值的值
dropna 如果为True,将不含所有条目均为NA的列
margins 添加行/列小计和总和(默认为False)
返回小费数据例子:
tips.pivot_table("tip_pct",index = ["time","smoker"],columns = "days",aggfunc = "len",margins = True)
day Fri Sat Sun Thur All
time smoker
Dinner No 3 45 57 1 106
Yes 9 42 19 NaN 70
Lunch No 1 NaN NaN 44 45
Yes 6 NaN NaN 17 23
ALL 19 87 76 62 244
交叉表:crosstab
data
sample nat han
0 1 USA Right
1 2 Japan Left
2 3 USA Right
3 4 Japan Left
4 5 Japan Left
5 6 Japan Left
6 7 USA Right
7 8 USA Right
8 9 Japan Left
9 10 USA Right
pd.crosstab(data.nat , data.han , margins = True)
han Left Right All
nat
Japan 2 3 5
USA 1 4 5
All 3 7 10
四、绘图与可视化 matplotlib.pyplot
4.1 .1图片与子图
设置图片尺寸大小:plt.figure(figsize = (20,12))
设置子图位置:plt.subplot2grid((3,3),(1,0),colspan = 2) #意思为一个3行3列的图片格,子图起始位置为(1,0),列(横)向延申2格
4.1.2 插入图例:plt.legend(loc = 'best') 自动选择最合适的位置
4.1.3 刻度、标签和图例
plt.plot(np.random.randn(1000).cumsum())
plt.xticks([0,250,500,750,1000],["one","two","three","four","five"],rotation = 30)#设置X轴标签
plt.title("My first matplotlib plot")#设置标题
plt.xlabel("Stages")#设置x轴标题
4.1.4 注释与子图加工text arrow annote
plt.plot(np.arange(100))
plt.annotate("360",xy = (50,50),xytext = (50,70),arrowprops = dict(facecolor = 'r',width = 3,headwidth = 6,headlength = 6))
plt.title("My two matplotlib plot")
4.1.5 图片的保存
plt.savefig("xxx.png",dpi = 400 , bbox_inches = "tight")
参数
fname 包含文件的路径及扩展名xx/xx/xx.png
dpi 每英寸点的分辨率,默认为100
facecolor,edgecolor 子图之外的图形背景的颜色,默认为w白色
format 文件格式
bbox_inches 要保存的图片范围,如果传递“tight”,将会去除掉图片周围空白的部分
4.1.6 显示中文设置
plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = ['SimHei']
五、时间序列
5.1 日期和时间数据的类型及工具
from datetime import datetime
now = datetime.now()
datetime.datetime(2019,8,13,22,23,52,72973)
now.year , now.month , now.day
(2019,8,13)
datetime既储存了日期,也储存了细到微秒的时间。timedelta表示两个datetime对象的时间差
delta = datetime(2011,1,7) - datetime(2008,6,24,8,15)
datetime.timedelta(926,56700)
delta.days
926
delta.seconds
56700
也可以为一个datetime对象加上一个timedelta或其整数倍来产生一个新的datetime
from datetime import timedelta
start = datetime(2011,1,7)
start + timedelta(12)
datetime.datetime(2011,1,19,0,0)
datetime模块中的类型
date 使用公历日历储存日历
time 将时间储存为小时、分钟、秒和微秒
datetime 储存日期和时间
timedelta 表示两个datetime值之间的差
tzinfo 用于储存时区信息的基本类型
5.1.1 字符串与datetime互相转换
stampe = datetime(2011,1,3)
value = str(stampe)
"2011-01-03 00:00:00"
datetime.strptime(value,"%Y-%m-%d")
datetime.datetime(2011,1,3,0,0)
datetime.strptime是在已知格式的情况下转换日期的好方式。然而每次都需要编写一个格式代码有点烦人
pandas主要时面向处理日期数组的,无论是用作轴还是用作DateFrame中的列to_datetime方法可以转换很多不同的日期表示格式
datestr = ["2011-07-06 12:00:00","2011-08-06 00:00:00"]
pd.to_datetime(datestr)
datetimeindex(["2011-07-06 12:00:00","2011-08-06 00:00:00"],dtype = "datetime64[ns]")
python 连接mysql
#导入第三方模块
import pymysql
#连接mysql数据库
cnn = pymysql.connect(host = 'localhost',user = 'root',password = 'teat',database = 'tset',port = 3306,charset = 'utd8')
#host:服务器 user:用户名 password:密码 database:数据库 port:端口
#读取数据
user = pd.read_sql('select * from topy',cnn)
关闭连接
cnn.close()
python sql操作读取数据
sale = pd.read_csv(....)
#导入第三方模块
import sqlite3
con = sqlite3.connect(':memory:') 连接数据库
sale.to_sql('sale',con)将DateFrame注册成可sql查询的表
newtable = pd._read_sql_query('select * from sale',con)