程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Numpy與Pandas

編輯:Python

部分圖片無法顯示需要pdf版的關注私我

NumPy

數組:數據類型一致

列表:指針數,不用數據類型一致

數組的維度根據需要的索引來確定

NumPy的數組:有序,類型相同 優先級:str>float>int

np.array(object,dtype=float) #把列表構建一個numpy數組,object是列表,dtype是類型numpy內置了一些類型 例:np.float32
np.ones(shape) #用1來填充
shape = (m,n) m行n列的二維數組
shape = (m) m個元素的一維數組 [1,2,3]
shape = (m,) m個元素的一維數組
shape = (m,1) m行1列的二維數組 [[1],[2],[3]]
shape = (1,n) 1行n列的二維數組 [[1,2,3]]
np.ones(shape) #用0來填充
shape=(2,3,4)
np.full(shape,fill_value=6) #用fill_value填充
np.eye(N=3,M=4,k=1) #單位矩陣 生成一個三階矩陣,默認M=N一般不用,k用來控制對角的移動
等差數
np.linspace(start,stop,num,endpoint=True) #等差數列 start起始數 stop結束數 num取幾個數 endpoint為True時保留最後一個否則不保留
np.arange(start,stop,step) #等差數列 start起使數 stop結束數 step步長(差值) 默認不取最後一個值
隨機數
np.random.randint(low,high,size) #隨機數 在low和high間取值,size等同於shape
np.random.randn(d0,d1....dn) #標准正態分布 d0一維的個數,d1二維的個數
np.random.normal(loc,scale,size) #普通正態分布 loc數學期望(接近的值) scale方差 size等同於shape
np.random.random(size) #生成0~1之間的隨機數
np.random.permutation(10) #生成一組隨機索引

ndarray的屬性

  • ndim:維度

  • shape:形狀

  • size:總長度

  • dtype:元素類型

    arr = np.random.randint(0,100,(5,4,3))
    arr.ndim #獲取維度
    arr.shape #獲取形狀
    arr.size #獲取總長度
    arr.dtype #獲取數組元素類型
    type(arr) #獲取數組類型
    

    索引

arr = np.array([[1,2,3],[4,5,6]])
#列表的索引方式
arr[0][0]
#numpy特有的索引
arr[0,0]=1 #賦值
arr[[1,2]]
#BOOL列表作為列表索引訪問,True對應的值會被返回
bool_list = [True,False,True,False,True]
arr[bool_list]

切片

所有切片都是左閉右開區間

#行切片
arr[0:2]
#列切片
arr[:,0:2] #:從頭切到位,前面的維度用:最後一個正常切片
#數據反轉
arr[::-1]

變形

arr.reshape((4,5)) #標准寫法,注意元素個數
arr.reshape(4,5)

級聯

arr1 = [[1,2,3],[4,5,6]]
arr2 = [[1,2,3],[4,5,6]]
np.concatenate((arr1,arr2),axis=0) #axis默認為0縱向連接,等於1時是橫向連接
np.hstack((arr1,arr2))#橫向連接 數組的行數要一致
np.vstack((arr1,arr2))#縱向連接 數組的列數要一致

切分


arr2 = [[1,2,3],[4,5,6],[1,2,3],[4,5,6]]
a1,a2 = np.split(arr,indices_or_sections=2,axis=0)#indices_or_sections切割的份數
a1,a2 = np.split(arr,indices_or_sections=[1,3],axis=1)#1前面的是一列1~3是一列3後面的是一列(多用於橫向切割維度內個數為不能等分的)
np.hsplit(arr,indices_or_sections=[1,3])#縱向切分
np.vsplit(arr,indices_or_sections=[1,3])#橫向切分

副本

所有賦值運算會改變原數據

可以使用copy()函數創建副本

copy_arr = arr.copy()

聚合操作

#求和
arr.sum()
arr.sum(axis=0) #求列方向的和,為1時是行
#最大值
arr.max()
#最大值索引
arr.argmax()
#最小值
arr.min()
#最小值索引
arr.argmin()
#平均值
arr.mean()
#標准方差(標准差) ((a1-mean)**2+(a2-mean)**2......(an-mean)**2)/n 數據波動
arr.std()
#方差
arr.var()
#中位數
np.median(arr)

廣播機制

  • 為缺失的維度補1
  • 假定缺失的元素用已有的值填充
#矩陣運算
np.dot(arr1,arr2)

排序

#改變原始數據
arr.sort()
#不改變
np.sort(arr)
#部分排序 k為正,排序最小的k個數,k為負,排序最大的k個 後面跟上切片[:k],[-k:]
np.partltion(arr,k)

Pandas

Pandas的數據結構

numpy array 提供了運算基礎

pandas 提供了業務邏輯的處理方法

Series 一維

Data Frame 二維

Series

類似於一維數組的對象,一維數組的強化版,增加了像字典一樣的key-value的訪問機制

字典:無序的集合

Series的創建

 #列表創建,name改變a不變,a是副本
name=['12','67','89']
a = Series(name)
#array創建,arr改變b改變,b是引用
b = Series(arr)
#index是顯性索引,沒有手動設置,默認顯示隱性索引
c = Series(data=name,index=['z','x','c'])
#字典構造 index的優先級高於字典的鍵值
dic={
'z':'a'}
d = Series(dic)

Series的索引和切片

索引

Series訪問完成兼容numpy數組訪問

#顯式索引訪問,類似字典訪問
d['z']
#使用loc,配合顯式索引
d.loc['z']
d.loc[['z']]
#使用iloc,隱式索引訪問
d.iloc[0]
d.iloc[[0]]
#使用帶索引的bool訪問,沒有索引會報錯,也可以直接用array和列表代替bool
bool = Series(data=[True,True],index=['z','x'])
name[bool]
#bool訪問一般配合表達式使用
name[name > 60]
切片
#數組切片
a[0:2]
#字典 索引使用顯式索引的都是閉區間
c['z':'c']
#顯式索引loc訪問
c.loc['z':'c']
#隱式iloc訪問 都是開區間
c.iloc[0:2]
Series屬性
#顯示形狀
c.shape
#顯示元素個數
c.size
#顯示顯式索引 獲取到的可以當列表用
c.index
(c.index=='a').any() #如果有a這個索引返回True,沒有any返回的是一個'列表'
#顯示數組
c.values
#查看前n個和後n個,切片操作,一般用於查看數據結構
c.head(2)
c.tail(2)
#pd.isnull,pd.notnull,或者自帶isnull(),notnull()函數檢測缺失數據
any() 判斷bool列表中是否至少存在一個True
all() 查看bool列表是否全是True
c.isnull().any() #判斷是否存在一個空值,為空返回True
c.notnull().all() #判斷是否全部不為空,為空返回False
#name屬性往往起標識用讓你知道這個數據是什麼
#根據值排序
c.sort_values(ascending=False) #False是降序默認為True
#根據索引排序
c.sort_index(ascending=False) #False是降序默認為True
#統計值的出現次數
R 最近消費時間
F 頻率
M 消費金額
c.value_counts() #統計次數
Series運算
#Series和一個數運算 和廣播機制一致
#Series和numpy運算 同等長度:隱式索引對齊(與廣播相似)
c.value #是一個numpy類型
#Series和Series運算,顯式索引對齊 a找a去計算 s1有s2沒有的索引相加就為NaN
s1 = Series(data-np.random.randint(0,10,size=5),index=list("abcde"))
s2 = Series(data-np.random.randint(0,10,size=5),index=list("abcde"))
s1 + s2
NaN和任何值運算都是NaN
#a找a去計算 s1有s2沒有的索引相加fill_value=0就為有值那一個設置空值為0
s1.add(s2,fill_value=0) #加
s1.sub(s2) #減
s1.mul(s2) #乘
s1.div(s2) #除
#Series也支持聚合
#Series和DataFrom都支持擴展,類似列表賦值
score['z'] = 0

Data Frame

Data Frame是一個[表格型]的數據結構,可以看做是由Series組成的字典 。Data Frame由按一定順序排列的多行數據組成。設計初衷是將Series從一維拓展到多維,Data Frame既有行索引,也有列索引。

  • 行索引:index

  • 列索引:columns

  • 值:values(numpy的二維數組)

    dic={
    
    'a':Series([1,2,3])
    'b':Series(['a','b','c'])
    }
    

Data Frame的創建

DataFrame(data,index,columns) #index行標簽,columns列標簽
df.columns #讀取列標簽
df.index #讀取行標簽
#從文件讀取DataFrame對象
pd.read_csv() #csv
pd.read_table() #txt
df = pd.read_excel(header=0,index_col=0,sheet_name=0) #excel header設置哪行作為列標簽,index_col設置哪列作為行標簽,sheet_name設置讀取的是哪張表裡的可以用索引可以寫名字
df.to_excel('路徑(保存的位置)')
pd.read_sql

使用Series構建Data Frame

#Series裡的name在轉換為DataFrame會變成列索引
Data Frame的索引

對列進行索引,可以將Data Frame的列獲取為一個Series,返回的Series擁有原Data Frame相同的索引,且name屬性已經設置好了,就是相應的列名

#用字典的方式訪問
df['a']
#使用標簽列表訪問列
df[['a','b']]
#屬性訪問
df.a
對行進行索引
#使用loc顯式
df.loc[0]
#使用iloc
df.iloc[0]
對元素索引的方法
#先行後列
df['a','B']
#使用loc
df.loc['a','B']
df['B'].loc['a'] #間接訪問,賦值可能出現問題
#使用iloc
df.iloc[0,1]

切片

#標簽處理的切片都是閉區間後不取

直接用中括號時:

  • 索引表示的是列索引
  • 切片表示的是行切片
df['A','B']#訪問不了列
#行切片
df.loc['a','b']
#列切片和二維數組一樣,先行後列
df.loc[:,'B']
#bool訪問索引對齊

Data Frame運算

DataFrame和一個數(廣播)
DataFrame和一個數組(numpy、Series)
如果行形狀一致可以運算 (numpy)
與Series運算要注意索引對齊 axis=0行索引對齊
df.add(s1,axis=0)
DataFrame和DataFrame(索引對齊,不分方向)

pandas缺失值

NaN不參與運算,參與運算的是np.nan,且np.nan和任何運算都是np.nan,None是一個對象,np.nan是一個浮點型

類型強制統一numpy且為空的時候浮點型的計算效率更高

pandas會自動把None自動優化為nan

#查看DataFrame的每一列元素類型
df.dtypes
#查看行方向空值,查看列時為1
df.isnull().any(axis=0)
#默認刪除行,axis控制方向,當any變為all時要一行全是空值才刪除
df.dropna(axis=0,how='any')
#使用一個數來填充空值
df.fillna(value=10)
#通常使用每一列的聚合指標來對每一列填充,索引對齊填充空值
df.fillna(value=user.mean())
#相鄰值來填充,axis是軸,backfill、bfill、pad、ffill前兩個是向後取值填充,後面的是向前,和軸有關系
df.fillna(axis=0,method='ffill')

多層級索引

#設置0和1行為列索引,設置0和1行為行索引
df = pd.read_execl('data.xlsx',header=[0,1],index_col=[0,1])
df.columns

創建多層級索引

#使用數組
arr = [['上半年','上半年','上半年','下半年','下半年','下半年'],['收入','成本','費用','收入','成本','費用']]
pd.MultiIndex.form_arrays(arr)
#使用tuple(元組)
tuples = (('上半年','收入'),('上半年','成本'),('上半年','費用'),('下半年','收入'),('下半年','成本'),('下半年','費用'))
pd.MultiIndex.form_tuples(tuples)
#使用product(推薦)
columns = pd.MultiIndex.form_product([['上半年','下半年'],['收入','成本','費用']])
data = np.random.randint(0,1000,size=(3,6))
index = ['92#','95#','90#'] #index =3 columns=6
DataFrame(data=data,index=index,columns=columns)

Series操作

#取92#上半年的收入,元組來表達
df2 = df.loc[92#]
df2[('上半年','收入')]
#也可以把多級索引變成單級索引
df2['上半年']['收入']
#切片
df[('上半年','收入'):('下半年','收入')]
#同時獲取值
df[[('上半年','收入'),('下半年','收入')]]

Data Frame的操作

index = ('期中','張三')
column = ['java']
df.loc[index,column]
df.set_index('a') #把a列設置為行索引
#隱式索引,只有順序沒有層級,永遠單ch
df.python.unique() #去重
df.iloc[0,1]#拿第一行和第二行
df.iloc[(0,0)]#拿第1行的第1個值

多層級的索引變性(stack)

#把列索引變成行索引,默認等於-1,把多級索引的第一個索引變下去 從裡往前數為level的值,會自動過濾空值
df.stack(level=-1)
#把行索引變成列索引,默認等於-1,把多級索引的第一個索引變上去,有空值會給你變成空值
df.unstack(level=-1)

pandas的匯總操作

numpy級聯不好用

pandas拼接分為兩種

級聯:pd.concat ,pd.append

合並:pd.merge ,pd,join

使用pd.concat()級聯

級聯方向上的形狀不同,同樣可以連接

簡單級聯

#objs是要參與級聯的pandas對象的列表、元組,可以通過axis改變方向
pd.concat((score1,score2),axis=0)
#忽略索引,重新索引原始表的索引沒意義,避免重復
pd.concat((score1,score2),ignore_index=True)
#原來的索引有意義又要避免重復可以設置成多層級索引
pd.concat((score1,score2),keys=['第一天','第二天'])

不匹配級聯

#out連接,外連接,保留連接表的所有字段,缺失值補空(默認)
pd.concat((score1,score2),join='outer')
#inner連接,內連接,只保留公共字段,會去空值會導致數據丟失
pd.concat((score1,score2),join='inner')
#自定義連接,join_axis只能傳入列表,列表裡要是index類型數據
pd.concat((score1,score2),join_axis=[pd.Index(['d','e']))
#左連接,右連接,只保留其中一張表的字段(兩張表連接)
pd.concat((score1,score2),pd.concat((score1,score2),join=[score1.columns]))
#使用append連接(縱向連接)
score1.append(score2)

使用pd.merge()合並(整合到一張表)

#合並只和列有關,參與合並的兩張表至少有一列有對應關系(內容上有一致,一對一,一對多,多對多裡的一種)
#一對一
pd.merge(tab1,tab2)
#多對一
pd.merge(tab1,tab3)
#多對多
#默認把字段相同的列合並,如果有多個列標簽相同會同時參考
pd.merge(tab3,tab4)
#key的規范化
#根據on設置參考的列標簽
pd.merge(tab3,tab4,on='手機型號')
#使用left_on和right_on來指定兩列來合並,左右兩邊的key都不相同時用
#如果合並的列不同名會都保留
r1=pd.merge(tab3,tab4,left_on='型號',right_on='產品')
#刪除型號一列,默認刪除行,所以要設置axis值,為True時修改上面的值r1改變
r1.drop(labels=['型號'],axis=1,inplace=True)
#left_index,用索引去和某一列的值做參照合並時用
r1=pd.merge(tab3,tab4,left_index=True,right_on='產品')

內合並和外合並

內合並:保留兩者都有的key(默認模式)

#inner保留相同的內容
#concat保留相同的標簽
#outer保留內容並集(保留所有)(外合並)
#left/right左右合並,只保留左表的或者右表的
pd.merge(tab1,tab2,how='inner')

列沖突

#對重復字段命名
pd.merge(tab3,tab4,on='手機型號',suffixes=['_下半年','_上半年'])

pandas數據處理

原始數據基本步驟:

  1. 空值處理
  2. 重復值處理
  3. 異常值處理

刪除重復元素

#查詢重復行
#沒有axis所以重復值只在行內查找,默認保存第一次出現的值,當keep='last'時保留最後一個,反之first,返回值是列表
df.duplicated(kepp='last')
#直接刪除
df.drop_duplicates(keep='last')
#查詢一行裡某幾列值相同
df.duplicated(subset=['python','java','php'])

映射

#replace屬於fillna的高級版本
#直接替換字符串
df.replace(to_replace='tom',value='TOM')
#替換數字
df.replace(to_replace=77,value=100)
#使用列表來替換
df.replace(to_replace=['lucy','tom','jack'],value=['lucy1','tom1','jack1'])
#使用字典替換
map_dict = {

'lucy':'LUCY'
}
df.replace(to_replace=map_dict)
#使用字典處理某一列,name列裡的lucy才替換
df.replace(to_replace={
'name':'lucy'},value='LUCY')
#正則替換,使用正則要開啟regex=True,表達式前要加r
df.replace(to_replace=r't.*',regex=True,value='con')
#針對Series的替換操作,ffill向前填充,(method不能在datafrom裡用)
df.replace(method='ffill',to_replace='tom')
#map是Series的函數,通常用來對某一列進行整體映射處理
map_dict{

'tom':'biejing',
'lucy':'shanghai'
}
map_dict.get('tom') #返回值---biejing
map_dict.get('lsad') #返回值---none
map_dict.get('lashd','meiyou') #返回值---meiyou
#找到name列,添加到df,字典裡的映射只能多不能少,少了會填空值
df['dizhi'] = df.name.map(map_dict)
#使用函數
#字典少了的解決辦法,map可以接收函數,可以用來自定義得到的值(下圖評分等級)
def map_name(name):
return map_dict(name,name) #如果字典裡有則返回字典裡的,沒有則返回傳入值
df['name'].map(map_name)
#lambda 表達式,傳入x返回x同學
df.name.map(lambda x:x+'同學')
#transform()
#只能傳入函數
df.name.transform(lambda x:x+'同學')

對一個Data Frame做遍歷的時候,默認便利的是它的列標簽(默認遍歷他的鍵,可以把dataframe當做字典來用)

for i in df:
print(i)
for k,v in df.items():
print('鍵'+k)
print('值'+v)

替換索引

#替換列索引
df.rename(columns={
'name':'姓名'})
#替換行索引
df.rename(index={
'張三':'李四'})
mapper = {

'張三':'tom',
'姓名':'名字'
}
#默認替換了行索引,axis=1替換列索引
df.rename(mapper=mapper,axis=1)
#替換多層級索引
mapper = {

'張三':'tom',
'姓名':'名字',
'上學期':'下學期'
}
#level設置類還是行方向的多層級索引的層級
df.rename(mapper=mapper,axis=1,level=-2)

使用聚合函數對數據異常值檢測和過濾

#每列的信息
df.info
#只對可以運算的列有效,查看數據基本信息
df.describe()
#異常值通用的界定方法:如果數據是呈標准正態分布的,明顯不同的數據std方差 |data| > 3*|data.std()|
np.abs(df) > 3*data.std()#每一列的每一個數都和該列的三倍方差比較(比較時索引對齊)
#離群點的檢測:數值型數據都可以使用離群點的方法來檢測異常
#take()排序,接收一個索引列表不是標簽列表
df.take([0,1,0,1],axis=0)
#配合np.random.randint()函數,配合take函數實現隨機
df.take(np.random.randint(5))
#當dataframe規模很大時,直接使用np.random.randit()函數,配合take()實現隨機抽樣

數據分類/組處理

#根據 分類 分組,產生一個分組對象
a = df.groupby('分類')
b = a.groups #查看分組對象的信息
#分組之後一定聚合,聚合只保留可運算的列
b.mean()
#對不同的列進行不同的聚合運算
b.agg({
'身高':'mean',
'體重':'max'
})
#多字段分組
a = df.groupby(['分類','學科'])

透視表

#透視表,數據匯總
pd.pivot_table(data=df,values='分數',index='分類',columns='學科',aggfunc='mean',fill_value=0)#空值填0

交叉表

#計算分組頻率
pd.crosstab(index=df['班級'],columns=df['姓名'])

高級聚合

#兩個相同
df.groupby('分類')['name'].mean
df.groupby('分類')['name'].apply(np.mean)
#傳函數,函數接收的是每一個分組
def asy(x):
print(x)
df.groupby('分類')['name'].apply(asy)
#transform也傳函數,返回值是全數值

1,0,1],axis=0)
#配合np.random.randint()函數,配合take函數實現隨機
df.take(np.random.randint(5))
#當dataframe規模很大時,直接使用np.random.randit()函數,配合take()實現隨機抽樣


## 數據分類/組處理
```python
#根據 分類 分組,產生一個分組對象
a = df.groupby('分類')
b = a.groups #查看分組對象的信息
#分組之後一定聚合,聚合只保留可運算的列
b.mean()
#對不同的列進行不同的聚合運算
b.agg({'身高':'mean',
'體重':'max'
})
#多字段分組
a = df.groupby(['分類','學科'])

透視表

#透視表,數據匯總
pd.pivot_table(data=df,values='分數',index='分類',columns='學科',aggfunc='mean',fill_value=0)#空值填0

交叉表

#計算分組頻率
pd.crosstab(index=df['班級'],columns=df['姓名'])

高級聚合

#兩個相同
df.groupby('分類')['name'].mean
df.groupby('分類')['name'].apply(np.mean)
#傳函數,函數接收的是每一個分組
def asy(x):
print(x)
df.groupby('分類')['name'].apply(asy)
#transform也傳函數,返回值是全數值

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved