python科學計算的基本方式:
向量化運算(矢量化運算),並行計算,摒棄了循環遍歷(標量運算),浪費內存
衡量一個人會不會用pandas做數據分析
- 會不會做聚合推導透視表,交叉表
- 會不會矢量化編程完成項目
自定義運算
apply():Series和DataFrame通用自定義運算函數(計算行/列)
map():Series用
applymap():DataFrame用計算單元格
如果pandas庫自帶的運算和函數不滿足需求,可以自定義函數,並同時將函數應用到pandas的每行/列或值上
應用函數主要用於替代傳統的for循環
可以將map和apply的參數x理解為for循環的i值(series就是單值,DataFrame就是每一行/列)
針對Series的map函數,會將自定義函數應用到Series對象的每個值
不直接用於單元格的算法
關於行列的思路,分割成每個單元格作比較
參數傳遞
-
apply(top, n=1, column='math') 在apply函數內定義參數,幫助傳入top內 def top(aa,n,columns='english')
axis=0按行操作,默認
- 給這一列的所有行,進行運算
axis=1按列操作
- 給這一行的所有列,進行運算
a = pd.Series([9,7,8,6],['a','b','c','d']) b = pd.DataFrame(np.arange(20).reshape(4,5),index=['a','b','c','d']) def ccc(x): return x.min() b.apply(ccc, axis=0) #給這一列的所有行,進行運算,所以結果和想的不一樣 # 自定義函數的參數x,用apply調用,在運算過程中標識DataFrame的1行或者1列(是series對象,可以理解為for循環遍歷,但是並行運算) def bbb(x): return pd.Series([x.min(),x.max()],index=['min','max']) #構建Series返回,結果就是返回DataFrame b.apply(bbb)
基本統計函數
pandas的統計運算方法和numpy基本一致
默認針對0軸(行)做運算,大部分函數可加參數axis-1改為列運算
- describe() 針對0軸的統計匯總,計數/平均值/標准差/最小值/四分位數/最大值,非數值型列,不計入(字符串)指標
- sum()計算數據的總和,按針對0軸計算(各行計算),針對1軸計算參數改為1
- count() 非nan值數量
- mean()/median()/mode() 計算數據的算數平均值/中位數/眾數
- var()/std() 計算數據的方差/標准差
- min()/max() 計算數據的最大值/最小值
- idxmin()/idxmax() 計算數據的第一個最大值/最小值所在的位置索引,給索引切片使用(自定義索引,排除null/na等空值)
pandas分組聚合-基礎
數據分析階段
數據規律(清洗階段后),下一個階段就是分組聚合,分組聚合只針對數值類型
- 對數據集分組並對各組應用一個函數是數據分析中的重要環境
- 一般將數據准備好后,首先就是計算分組統計
- sql能夠方便的連接,過濾。轉換和聚合數據,但sql能執行的分組運算種類優先,pandas則強大靈活很多
聚合操作,一般是指應用某種方法(自定義的聚合函數或者系統自帶的pandas的統計方法等)給數據降維
聚合函數常用
- 平均值:mean() 透視表
- 個數:size() 交叉表、
分組的作為行索引,聚合作為值(series),聚合作為列索引(DataFrame)
數據分組 分組聚合:groupby(),一般指以下一個或者多個操作步驟的集合 splitting 分組:將列分割為n組 applying 應用:將每個分組應用聚合函數 combining合並:合並分組和聚合的結果 name,score name ,score name ,score a 1 a 1,2 a 2 a 2 ====> b 3,4 ===> b 4 b 3 group by name max(score) b 4
以單列基准分組,聚合其他
a_values = [{"name": "鍾洋","chinese": 23,"math": 25,"english": 25,"test": "一" },{"name": "李敏","chinese": 99,"math": 48,"english": 78,"test": "一" },{"name": "夏軍","chinese": 70,"math": 83,"english": 12,"test": "一" },{"name": "姚明","chinese": 65,"math": 12,"english": 73,"test": '二' },{"name": "夏軍","chinese": 80,"math": 63,"english": 45,"test": '二' },{"name": "夏軍","chinese": 90,"math": 82,"english": 65,"test": '三' },{"name": "李帥","chinese": 99,"math": 58,"english": 78,"test": "一"}] df = pd.DataFrame(a_values) # 每位同學每課成績的平均分 # 分組 x = df.groupby('name').mean() # 每位同學考試的次數 y = df.groupby('name').size() # 將分組傳遞給變量 class_group = df.groupby('name') class_group.size() # 如果不想使用分組作為列索引,設置參數as_index=False x = df.groupby('name',as_index=False).mean()
以多列為基准
- 多列分組
- 單列或多列聚合
# 單列多列分組 df.groupby('name').mean() df.groupby(['name','test']).mean()
多列單列聚合
- 對於大數據集,很可能值需要對部分進行聚合
- 下面三種寫法結果一樣
- 分組聚合參數,傳入標量形式得單個列名,返回Series
- 分組聚合參數,傳入列表或數組,返回DataFrame(默認傳入所以列)
# 對除分組基准列以外得所有列進行聚合 df.groupby('name').sum() # 多列聚合, 聚合除分組以外得所有列 # 分組后,只對chinese單列聚合 df['chinese'].groupby(df['name']).sum() # 效率高,但是寫法詭異 df.groupby('name')['chinese'].sum() # 書寫簡單,效率高,推薦,返回Series df.groupby('name')[['chinese']].sum() # 書寫簡單,效率高,推薦,返回DataFrame # 分組后,多列聚合 df.groupby('name')['chinese'].sum() # 書寫簡單,效率高,推薦
分組聚合進階
本質上 groupby傳入得數據並不是行索引或列索引,而是任意一個和數據結構對應得序列(布爾,列表,數組,字典,Series)
- 根據列表做分組基准
- 根據字典或者Series做分組基准
- 根據函數做分組基准
- 根據層次化索引得級別做分組基准
# 根據列表分組,列表值得個數必須和表格行或列數對應 df.groupby('name').size() #分組參數是列索引,直接獲取某列得值 df.groupby(df['name']).size() #手動將列值傳入分組參數 ### df_list = ['aa','bb','cc','dd','ee','ff','gg'] # 自定義列表作為分組基准 df.groupby(df_list).size() #set_index把其中一列作為行索引 mapping = {'李敏':'one','姚明':'two'} df2 = df.set_index('name') df2.groupby(mapping).sum() # 使用seies進行分組 df2.groupby(pd.Series(mapping)).size()
通過函數分組
- 比起字典或者series,函數是一種更原生得方法定義分組映射
- 任何被當作分組鍵得函數都會在各個索引值上被調用一次,其返回值就會被作用分組基准
people = pd.DataFrame( np.random.randn(5,5), columns=['a','bc','c','d','e'], index=['Joe','Steve','wes','jim','travis'] ) people.iloc[2:3,[1,2]] = np.nan # len把行索引字符得個數作為分組基准 people.groupby(len).sum() # a = [3,5,3,3,6] people.groupby(a).sum() # ccc = ['one','one','one','two','two'] people.groupby([len,ccc]).sum() #joe wes既有3個字符,又屬於one ,針對行索引做的分組
#使用函數分組 people.groupby(len,axis=1).sum() # zzz = ['one','one','one','two','two'] people.groupby([len,zzz],axis=1).sum()
# lianxi,輸出每個學生在每次考次數中得數學平均分
從一個原始大表中抽取一個符合需求得小標
df.groupby(['name','test']).mean() # 3維度 df.groupby(['name','test'])['math'].mean() #2維Series pd.DataFrame(df.groupby(['name','test'])['math'].mean() ) df.groupby(['name','test'])['math'].mean().unstack().fillna(0).astype(np.int) #2維series轉換DataFrame
df.groupby(['name','test'])['math'].mean().unstack().fillna(0).astype(np.int) #2維series轉換DataFrame # 稱之為透視表 抽出1列,分組后作為行索引 抽出1列,分組后作為列索引 抽出1列,平均值聚合后作為值
根據層次化索引得級別分組
要根據層次化索引得級別,使用level關鍵字傳遞級別序號或名字
colums = pd.MultiIndex.from_arrays([['US','US','US','JP','JP',],[1,3,5,1,3]],names=['city','tenor']) hier_df = pd.DataFrame(np.random.randn(4,5),columns=colums) hier_df.groupby(level='city',axis=1).sum() #默認按照行分組 # 按行分組,自定義布爾數組做分組基准 ddd = [True,True,False,False,False,False,True] df.groupby(ddd).sum() # 按照列分組 ddd = [True,True,False,False,False] df.groupby(ddd,axis=1).sum() # 按列分組,自定義布爾數組做分組基准 df.groupby(df.dtypes,axis=1).sum()
#假設以知列得分組關系后,並希望根據分組計算列得和 mapping={'a':'red','bc':'red','c':'bule','d':'bule','e':'red','f':'orange' } # 多寫或少寫不會執行,多了一個f,不會影響分組 people.groupby(mapping,axis=1).sum()