一、數據結構和序列
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)