pandas 基础

pandas基础

numpy 能够适合的处理数值型数据,而pandas适合处理(字符串,时间序列)
2.Pandas安装
pip3 install pandas
 -- pandas 中常用的俩个库 Series 和 DataFrame。
    -- Series
    	-- values: 一组数据(ndarray类型)
        -- index : 相关的数据索引标签
        -- Series 的创建 (只能是一维的)
        	-- 由列表或numpy数组创建
            -- 由字典创建
    -- Series 是一个一维数组对象 ,类似于 NumPy 的一维 array。它除了包含一组数据还包含一组索引,所以可以把它理解为一组带索引的数组。
    import pandas as pd
    from pandas import Series,DataFrame
    Series(data=[1,2,3]) 
    # 反回值
    0    1
	1    2
	2    3
    Series(data=[1,2,3],index=['a','b','c']) #index是用来指定显示索引的(显示索引不会覆盖隐式索引)
    a    1
	b    2
	c    3
	dtype: int64
    -- Series的索引和切片操作
    s =  Series(data=[1,2,3],index=['a','b','c'])
     -- 索引的访问
        s[0]
        s['a']
        s.a
        s[1,2]
     -- 切片操作
     	s[0:3]
        s['a':'c']
     -- s.shape # 返回元素属性
     -- s.size # 返回元素个数
     -- s.index # 返回索引
     -- s.values # 返回值
     -- s.head(n) # 显示前n个元素
     -- s.tail(n) # 显示后n个元素
     -- s.unique() # 用来去重的
     -- s.nunique() #返回去重后的个数
     -- s.isnull() # 返回是不是为空(空是True不空为False)
     -- s.notnull() # 用来检测元素是否为非空
  -- Series的算术运算
  	s1 = Series(data=[1,2,3],index=['a','b','c'])
    s2 = Series(data=[1,2,3],index=['a','d','c'])
    s3 = s1+s2
	# a    2.0
	# b    NaN
	# c    6.0
	# d    NaN
	# dtype: float64
    
   -- DataFrame
	-- DataFrame 是一个【表格型】的数据结构,DataFrame由按一定顺序排列的多列数组组成,设计初衷是将Series的使用场景从一维拓展到多维,DataFrame即有行索引,也有列索引。
    -- 行索引:index
    -- 列索引:columns
    -- 值:values 
    
   -- DataFrame 的创建
		-- ndarray创建
    	-- 字典创建
    DataFrame(data=[[1,2,3],[4,5,6]]) # 数组
    dic={
        'name':['maji','henbang'],
        'day':['还是很棒','真的好棒',100]
    } 
    DataFrame(data=dic) #字典
    DataFrame(data = np.random.randint(0,100,size=(3,2))) 
    --  DataFrame(data = np.random.randint(0,100,size=(3,2),index=['q','w','e'],columns=['A','B'])) #显示索引
    -- index 行索引 columns 列索引 
  -- DataFrame的属性
	-- values 返回值
    -- columns 返回列索引
    -- index 返回行索引
    -- shape 返回形状	
 -- DataFrame索引操作重点
df = DataFrame(data=np.random.randint(0,100,size=(5,4)),columns=['q','w','e','r'],index=['A','B','C','D','E'])
            q   w   e   r
        A  93  30  23  84
        B  15  18  57  11
        C   4  29   6  36
        D  30  99  94   2
        E  11   4  35  67
	-- 对行进行索引
    	-- 索引取列 df['q'] # 显示索引取值列
        -- -- df.a # 显示索引取值列
        -- df.iloc[:,0] # 隐式索引取列
        -- df[0] # 隐式索引取行
        -- df['A'] # 显示索引取值行
        A    82
        B    88
        C    51
        D    23
        E    63
        Name: q, dtype: int32
   	--	取元素
    	df.loc['B','q']
        df.iloc[1,1]
        df.iloc[[0,1],2]
    -- 队列进行索引
    -- 对元素进行索引
    
    -- 切片
    	-- df[0:2] # 切行
        -- df.iloc[:,0:2] # 切列
    -- df索引和切片操作
    	- 索引:
        	df[col]:取列
            df.loc[index]:取行
            df.iloc[index,loc]:去元素
        - 切片
        	df[index1:index3] # 切行
            df.iloc[:col1:col3] # 切列
 
DataFrame运算同Series

DataFrame基本操作

更加详细的内容可以查看:https://blog.csdn.net/hhtnan/article/details/80080240 (基本函数整理)
一.  DataFrame的创建
  创建一个空的dataframe 
df=pd.DataFrame(columns={"a":"","b":"","c":""},index=[0])
  out:
a = [['2', '1.2', '4.2'], ['0', '10', '0.3'], ['1', '5', '0']]
df = pd.DataFrame(a, columns=['one', 'two', 'three'])
print df
  out:
  one  two three
0   2  1.2   4.2
1   0   10   0.3
2   1    5     0
   用numpy的矩阵创建dataframe
array = np.random.rand(5,3)
df = pd.DataFrame(array,columns=['first','second','third'])
  用dict的数据创建DataFrame
data = { 'row1' : [1,2,3,4], 'row2' : ['a' , 'b' , 'c' , 'd'] }
df = pd.DataFrame(data)
dict = { 'row1' : [1,2,3,4], 'row2' : ['a' , 'b' , 'c' , 'd'] }
df = pd.DataFrame.from_dict(dict,orient='index').T
  读取csv或者excel文件为DataFrame格式
df=pd.read_csv('D:/Program Files/example.csv')
  excel一个表格中可能有多个sheet,sheetname可以进行选取
df = df.read_excel('D:/Program Files/example.xls',sheetname=0)

二. DataFrame的一些描述和类型
   describe会显示dataframe的一些基本统计数据,数量、均值、中位数、标准差等
   head会显示dataframe的前几行,后几行:
print df.describe()
print df.head()<br>print df.tail(10)
  单独计算某列的统计值
df['one'].sum()
df['one'].mean()
df['one'].count()
df['one'].max()
df['one'].min()
  查看dataframe的数据类型:
print (df.dtypes)
  查看dataframe的数据数目:
print (df.size)
  查看dataframe的形状:
print (df.shape)
 返回列数:
print (df.ndim)
  查看横纵坐标的标签名:
print (df.axes)
三. DataFrame的切片

  -- iloc索引或切片(iloc中只能取整数值):
print df.iloc[1,:] #第1行,所有列
print df.iloc[:,[0,2]] #第0行,第0列和第2列
print df['one'].iloc[2] #列名索引+行号
	-- loc索引或切片(loc中可以取str):
print data.loc[0:1, ['one', three']] #筛选出dataframe中有某一个或某几个字符串的列:
   -- list=['key1','key2']
   -- df = df[df['one'].isin(list)]
                     
 -- 筛选出dataframe中不含某一个或某几个字符串的列,相当于反选
-- df = df[~df['one'].isin(list)]

四. 缺失值的处理
  -- 缺失值可以删除也可以用均值或者0等数填充:
		-- df.fillna(df1.mean())
		-- df.fillna(0)
                     
 -- 删除缺失值时可以指定列:
	-- df = df.dropna(subset=['one','two'])
                     
五. 去重、删除行或列
	去重需要在subset指定哪一列的值进行筛选,如果不选择的话默认整行的值全部一样才去掉first表示保留第一个出现的值所在行,last表示保留最后一个出现的重复值所在的行,false表示重复的行全部删除

	-- df=df.drop_duplicates(subset='one',keep='first')
                     
 - 去除有NaN值的行或列(axis=0去除行,=1去除列):
    -- df = df.dropna(axis=0)
    -- df = df.dropna(axis=1)
                     
 --去除某一列:
	--df = df.drop(['one'],axis=1)
                     
 -- 去除含有某一个数的行:
   -- row_list = df[df.one == 2].index.tolist() # 获得含有该值的行的行号
   -- df = df.drop(row_list)
 六. DataFrame的修改

  修改数据类型

	- df['one']=pd.DataFrame(df['one'],dtype=np.float)
 -- 修改列名(需要写上所有列名,包括需要修改的和不需要修改的):

	- df.columns = ['first','second','all']
 -- 修改列名(只需写上需要修改的列)
	-- df.rename(columns = {'one':'first','two':'second'},inplace = True) #inplace=True表示修改df,若为False表示只返回一个修改后的数据
 -- 重排序(by可以取多个列名,默认升序):
	-- df = df.sort_values(by=['one'],ascending = True)
	-- df = df.sort_index(axis = 0,ascending = True,by = 'one')
	-- df = df.sort(columns = ['one'],axis = 0,ascending = True)
  修改数据
	-- df.iloc[1,2] = 10
 -- 用已有的列进行运算创建新的列
	--df['new_colume'] = df['one'] + df['two']   
七. dataframe更改索引
 -- 当删除掉不需要的行时,行索引会变的不连续,这时候可以重新设计新的索引
    1df['index']=range(len(df['one']))
    2df.set_index('index')
 -- 设置时间序列为索引
    1dd = pd.date_range(start='4/1/2018',periods=5)
    2#dd = pd.date_range('4/1/2018','4/5/2018')
    3df = df.set_index(dd)
八. 添加新的行,将两个dataframe连接到一起

  axis表示连接的方向,axis=0表示两个dataframe的行数会增加,如果列名相同则直接共用列,如果列名不同会生成新的列;axis=1,表示会加上新的列

1
df=pd.concat([df,df],axis=0) # 连接后行数是以前的2倍,列数不变
   在dataframe添加新的行

1
df = df.append(df.loc[2,:],,ignore_index=True)
  如果两个dataframe的列名是一样的,也可以用merge:

1
df = pd.merge(df,df)
  

 

九. DataFrame的输出

  输出为excel或者csv格式,csv文件里的数据被读取时数据类型默认为object,excel则会保留原有的数据类型

1
2
df.to_excel('path/filename.xls')
df.to_csv('path/filename.csv')
  输出为numpy的矩阵格式

1
matrix = df.ax_matrix()
  输出为dict格式

1
dict = df.to_dict(orient="dict")

pandas 网上百度教程

Python之Pandas使用教程
1.Pandas概述
Pandas是Python的一个数据分析包,该工具为解决数据分析任务而创建。
Pandas纳入大量库和标准数据模型,提供高效的操作数据集所需的工具。
Pandas提供大量能使我们快速便捷地处理数据的函数和方法。
Pandas是字典形式,基于NumPy创建,让NumPy为中心的应用变得更加简单。
2.Pandas安装
pip3 install pandas
3.Pandas引入
import pandas as pd
4.Pandas数据结构
4.1Series
复制代码
import numpy as np
import pandas as pd
s=pd.Series([1,2,3,np.nan,5,6])
print(s)
 
----------执行以上程序,返回的结果为----------
0    1.0
1    2.0
2    3.0
3    NaN
4    5.0
5    6.0
dtype: float64
复制代码
4.2DataFrame
DataFrame是表格型数据结构,包含一组有序的列,每列可以是不同的值类型。DataFrame有行索引和列索引,可以看成由Series组成的字典。

复制代码
import numpy as np
import pandas as pd
 
dates=pd.date_range('2019-08-01',periods=6)
pd=pd.DataFrame(np.random.randn(6,4),index=dates,columns=['A','B','C','D'])
print('输出6行4列的表格:')
print(pd)
print('\n')
 
print('输出第二列:')
print(pd['B'])
print('\n')
 
----------执行以上程序,返回的结果为----------
输出6行4列的表格:
                   A         B         C         D
2019-08-01  0.796050 -0.383286 -1.465294 -0.272321
2019-08-02 -1.431981 -0.875381  1.371449  0.321703
2019-08-03 -1.497636  1.258925 -1.374210 -0.765626
2019-08-04  2.518305  0.125094  2.647512 -0.024748
2019-08-05 -0.319238  0.395384 -0.582052 -0.396132
2019-08-06 -0.519434  1.873216  1.685524 -1.493000

输出第二列:
2019-08-01   -0.383286
2019-08-02   -0.875381
2019-08-03    1.258925
2019-08-04    0.125094
2019-08-05    0.395384
2019-08-06    1.873216
Freq: D, Name: B, dtype: float64
 
-------------------------------------------
import numpy as np
import pandas as pd
from datetime import datetime as dt
 
print('通过字典创建DataFrame:')
df_1=pd.DataFrame({'A':1.0,
'B':pd.Timestamp(2019,8,19),
'C':pd.Series(1,index=list(range(4)),dtype='float32'),
'D':np.array([3]*4,dtype='int32'),
'E':pd.Categorical(['test','train','test','train']),
'F':'foo'})
print(df_1)
print('\n')
 
print('返回每列的数据类型:')
print(df_1.dtypes)
print('\n')
 
print('返回行的序号:')
print(df_1.index)
print('\n')
 
print('返回列的序号名字:')
print(df_1.columns)
print('\n')
 
print('把每个值进行打印出来:')
print(df_1.values)
print('\n')
 
print('数字总结:')
print(df_1.describe())
print('\n')
 
print('翻转数据:')
print(df_1.T)
print('\n')
 
print('按第一列进行排序:')
#axis等于1按列进行排序 如ABCDEFG 然后ascending倒叙进行显示
print(df_1.sort_index(1,ascending=False))
print('\n')
 
print('按某列的值进行排序:')
print(df_1.sort_values('E'))
print('\n')
 
----------执行以上程序,返回的结果为----------
通过字典创建DataFrame:
     A          B    C  D      E    F
0  1.0 2019-08-19  1.0  3   test  foo
1  1.0 2019-08-19  1.0  3  train  foo
2  1.0 2019-08-19  1.0  3   test  foo
3  1.0 2019-08-19  1.0  3  train  foo

返回每列的数据类型:
A           float64
B    datetime64[ns]
C           float32
D             int32
E          category
F            object
dtype: object

返回行的序号:
Int64Index([0, 1, 2, 3], dtype='int64')

返回列的序号名字:
Index(['A', 'B', 'C', 'D', 'E', 'F'], dtype='object')

把每个值进行打印出来:
[[1.0 Timestamp('2019-08-19 00:00:00') 1.0 3 'test' 'foo']
 [1.0 Timestamp('2019-08-19 00:00:00') 1.0 3 'train' 'foo']
 [1.0 Timestamp('2019-08-19 00:00:00') 1.0 3 'test' 'foo']
 [1.0 Timestamp('2019-08-19 00:00:00') 1.0 3 'train' 'foo']]

数字总结:
         A    C    D
count  4.0  4.0  4.0
mean   1.0  1.0  3.0
std    0.0  0.0  0.0
min    1.0  1.0  3.0
25%    1.0  1.0  3.0
50%    1.0  1.0  3.0
75%    1.0  1.0  3.0
max    1.0  1.0  3.0

翻转数据:
                     0                    1                    2                    3
A                    1                    1                    1                    1
B  2019-08-19 00:00:00  2019-08-19 00:00:00  2019-08-19 00:00:00  2019-08-19 00:00:00
C                    1                    1                    1                    1
D                    3                    3                    3                    3
E                 test                train                 test                train
F                  foo                  foo                  foo                  foo

按第一列进行排序:
     F      E  D    C          B    A
0  foo   test  3  1.0 2019-08-19  1.0
1  foo  train  3  1.0 2019-08-19  1.0
2  foo   test  3  1.0 2019-08-19  1.0
3  foo  train  3  1.0 2019-08-19  1.0

按某列的值进行排序:
     A          B    C  D      E    F
0  1.0 2019-08-19  1.0  3   test  foo
2  1.0 2019-08-19  1.0  3   test  foo
1  1.0 2019-08-19  1.0  3  train  foo
3  1.0 2019-08-19  1.0  3  train  foo
 
复制代码
5.Pandas选择数据
复制代码
import numpy as np
import pandas as pd
 
dates=pd.date_range('2019-08-01',periods=6)
df=pd.DataFrame(np.random.randn(6,4),index=dates,columns=['A','B','C','D'])
print('输出6行4列的数据:')
print(df)
 
print('打印B列数据:')
print(df['B'])
 
----------执行以上程序,返回的结果为----------
输出6行4列的数据:
                   A         B         C         D
2019-08-01 -0.856790 -1.968381 -0.590032 -0.511943
2019-08-02  0.032420  0.750065 -1.168060 -1.571403
2019-08-03  0.962793 -2.377613  1.447871 -1.515988
2019-08-04  1.078565  1.780728 -0.060782  1.393749
2019-08-05 -1.785669  1.161425  0.440988  1.233997
2019-08-06 -0.740927 -0.877388 -0.868203  1.395331

打印B列数据:
2019-08-01   -1.968381
2019-08-02    0.750065
2019-08-03   -2.377613
2019-08-04    1.780728
2019-08-05    1.161425
2019-08-06   -0.877388
Freq: D, Name: B, dtype: float64
复制代码
切片选择

复制代码
print('切片选择:')
print(df[0:3],df['20190801':'20190804'])
 
----------执行以上程序,返回的结果为----------
切片选择:
                   A         B         C         D
2019-08-01 -0.456445 -1.641900  0.878254 -0.265412
2019-08-02  0.223910 -1.524222  0.428250  0.410542
2019-08-03 -1.248945  0.649155 -1.039407  0.138473                   
                   A         B         C         D
2019-08-01 -0.456445 -1.641900  0.878254 -0.265412
2019-08-02  0.223910 -1.524222  0.428250  0.410542
2019-08-03 -1.248945  0.649155 -1.039407  0.138473
2019-08-04 -1.135849  1.404054 -0.771489 -0.685064
复制代码
根据标签loc-行标签进行选择数据

复制代码
print('根据行标签进行选择数据:')
print(df.loc['2019-08-01',['A','B']])
 
----------执行以上程序,返回的结果为----------
根据行标签进行选择数据:
A   -0.495304
B   -0.083505
Name: 2019-08-01 00:00:00, dtype: float64
复制代码
根据序列iloc-行号进行选择数据

复制代码
import numpy as np
import pandas as pd
 
print('输出第三行第一列的数据:')
print(df.iloc[3,1])
print('\n')
 
print('进行切片选择:')
print(df.iloc[3:5,0:2])
print('\n')
 
print('进行不连续筛选:')
print(df.iloc[[1,2,4],[0,2]])
 
----------执行以上程序,返回的结果为----------
输出第三行第一列的数据:
1.2355112660049548

进行切片选择:
                   A         B
2019-08-04 -0.943150  1.235511
2019-08-05 -0.245097 -1.272304

进行不连续筛选:
                   A         C
2019-08-02 -0.212743 -0.584698
2019-08-03  0.012863 -0.896789
2019-08-05 -0.245097  2.646507
复制代码
根据混合的两种ix

复制代码
import numpy as np
import pandas as pd
 
print(df.ix(:3,[A,C]))
 
----------执行以上程序,返回的结果为----------
                   A         C
2019-08-01  1.591064  1.272731
2019-08-02  1.820216  0.657560
2019-08-03  0.358265 -1.197687
复制代码
根据判断筛选

复制代码
import numpy as np
import pandas as pd
 
print('根据判断筛选:')
print(df[df.A>0])
 
----------执行以上程序,返回的结果为----------
根据判断筛选:
                   A         B         C         D
2019-08-01  1.098786  0.261861  1.430775 -1.161001
2019-08-05  0.527853 -0.612058 -0.906565  1.279515
复制代码
 6.Pandas设置数据
根据loc和iloc设置

复制代码
import numpy as np
import pandas as pd
 
dates=pd.date_range('2019-08-01',periods=6)
df=pd.DataFrame(np.arange(24).reshape(6,4),index=dates,columns=['A','B','C','D'])
print('输出6行4列的数据:')
print(df)
print('\n')
 
print('更改后的数据:')
df.iloc[2,2]=999
df.loc['2019-08-01','D']=999
print(df)
print('\n')
 
----------执行以上程序,返回的结果为----------
输出6行4列的数据:
             A   B   C   D
2019-08-01   0   1   2   3
2019-08-02   4   5   6   7
2019-08-03   8   9  10  11
2019-08-04  12  13  14  15
2019-08-05  16  17  18  19
2019-08-06  20  21  22  23

更改后的数据:
             A   B    C    D
2019-08-01   0   1    2  999
2019-08-02   4   5    6    7
2019-08-03   8   9  999   11
2019-08-04  12  13   14   15
2019-08-05  16  17   18   19
2019-08-06  20  21   22   23
复制代码
根据条件设置

复制代码
import numpy as np
import pandas as pd
 
print('根据条件设置:')
df[df.A>0]=999
print(df)
 
----------执行以上程序,返回的结果为----------
根据条件设置:
              A    B    C    D
2019-08-01    0    1    2  999
2019-08-02  999  999  999  999
2019-08-03  999  999  999  999
2019-08-04  999  999  999  999
2019-08-05  999  999  999  999
2019-08-06  999  999  999  999
复制代码
根据行或列设置

复制代码
import numpy as np
import pandas as pd
 
print('根据行或列设置:')
df['C']=np.nan
print(df)
 
----------执行以上程序,返回的结果为----------
根据行或列设置:
              A    B   C    D
2019-08-01    0    1 NaN  999
2019-08-02  999  999 NaN  999
2019-08-03  999  999 NaN  999
2019-08-04  999  999 NaN  999
2019-08-05  999  999 NaN  999
2019-08-06  999  999 NaN  999
复制代码
添加数据

复制代码
import numpy as np
import pandas as pd
 
print('添加数据:')
df['E']=pd.Series([1,2,3,4,5,6],index=pd.date_range('2019-08-03',periods=6))
print(df)
 
----------执行以上程序,返回的结果为----------
添加数据:
              A    B   C    D    E
2019-08-01    0    1 NaN  999  NaN
2019-08-02  999  999 NaN  999  NaN
2019-08-03  999  999 NaN  999  1.0
2019-08-04  999  999 NaN  999  2.0
2019-08-05  999  999 NaN  999  3.0
2019-08-06  999  999 NaN  999  4.0
复制代码
7.Pandas处理丢失数据
处理数据中NaN数据

复制代码
import numpy as np
import pandas as pd
 
dates=pd.date_range('2019-08-01',periods=6)
df=pd.DataFrame(np.arange(24).reshape(6,4),index=dates,columns=['A','B','C','D'])
df.iloc[0,1]=np.nan
df.iloc[1,2]=np.nan
print('输出6行4列的数据:')
print(df)
print('\n')
print('使用dropna()函数去掉NaN的行或列:')
print(df.dropna(0,how='any'))#0对行进行操作 1对列进行操作 any:只要存在NaN即可drop掉 all:必须全部是NaN才可drop
print('\n')
print('使用fillna()函数替换NaN值:')
print(df.fillna(value=0))#将NaN值替换为0
print('\n')
print('使用isnull()函数判断数据是否丢失:')
print(pd.isnull(df))
 
----------执行以上程序,返回的结果为----------
输出6行4列的数据:
             A     B     C   D
2019-08-01   0   NaN   2.0   3
2019-08-02   4   5.0   NaN   7
2019-08-03   8   9.0  10.0  11
2019-08-04  12  13.0  14.0  15
2019-08-05  16  17.0  18.0  19
2019-08-06  20  21.0  22.0  23

使用dropna()函数去掉NaN的行或列:
             A     B     C   D
2019-08-03   8   9.0  10.0  11
2019-08-04  12  13.0  14.0  15
2019-08-05  16  17.0  18.0  19
2019-08-06  20  21.0  22.0  23

使用fillna()函数替换NaN值:
             A     B     C   D
2019-08-01   0   0.0   2.0   3
2019-08-02   4   5.0   0.0   7
2019-08-03   8   9.0  10.0  11
2019-08-04  12  13.0  14.0  15
2019-08-05  16  17.0  18.0  19
2019-08-06  20  21.0  22.0  23

使用isnull()函数判断数据是否丢失:
                A      B      C      D
2019-08-01  False   True  False  False
2019-08-02  False  False   True  False
2019-08-03  False  False  False  False
2019-08-04  False  False  False  False
2019-08-05  False  False  False  False
2019-08-06  False  False  False  False
复制代码
8.Pandas导入导出
pandas可以读取与存取像csv、excel、json、html、pickle等格式的资料,详细说明请看官方资料

复制代码
import numpy as np
import pandas as pd
 
print('读取csv文件:')
data=pd.read_csv('test2.csv')
print(data)
print('将资料存储成pickle文件:')
print(data.to_pickle('test3.pickle'))
 
----------执行以上程序,返回的结果为----------
读取csv文件:
   A  B  C  D
0  1  1  1  1
1  2  2  2  2
2  3  3  3  3

将资料存储成pickle文件:
None
复制代码
9.Pandas合并数据
axis合并方向

复制代码
import numpy as np
import pandas as pd
 
df1=pd.DataFrame(np.ones((3,4))*0,columns=['a','b','c','d'])
df2=pd.DataFrame(np.ones((3,4))*1,columns=['a','b','c','d'])
df3=pd.DataFrame(np.ones((3,4))*2,columns=['a','b','c','d'])
res=pd.concat([df1,df2,df3],axis=0,ignore_index=True)#0表示竖项合并 1表示横项合并 ingnore_index重置序列index index变为0 1 2 3 4 5 6 7 8
print(res)
 
----------执行以上程序,返回的结果为----------
     a    b    c    d
0  0.0  0.0  0.0  0.0
1  0.0  0.0  0.0  0.0
2  0.0  0.0  0.0  0.0
3  1.0  1.0  1.0  1.0
4  1.0  1.0  1.0  1.0
5  1.0  1.0  1.0  1.0
6  2.0  2.0  2.0  2.0
7  2.0  2.0  2.0  2.0
8  2.0  2.0  2.0  2.0
复制代码
join合并方式

复制代码
import numpy as np
import pandas as pd
 
df1=pd.DataFrame(np.ones((3,4))*0,columns=['A','B','C','D'],index=[1,2,3])
df2=pd.DataFrame(np.ones((3,4))*1,columns=['B','C','D','E'],index=[2,3,4])
print('第一个数据为:')
print(df1)
print('\n')
print('第二个数据为:')
print(df2)
print('\n')
 
print('join行往外合并:相当于全连接')
res=pd.concat([df1,df2],axis=1,join='outer')
print(res)
print('\n')
 
print('join行相同的进行合并:相当于内连接')
res2=pd.concat([df1,df2],axis=1,join='inner')
print(res2)
print('\n')
 
print('以df1的序列进行合并:相当于左连接')
res3=pd.concat([df1,df2],axis=1,join_axes=[df1.index])
print(res3)
 
----------执行以上程序,返回的结果为----------
第一个数据为:
     A    B    C    D
1  0.0  0.0  0.0  0.0
2  0.0  0.0  0.0  0.0
3  0.0  0.0  0.0  0.0

第二个数据为:
     B    C    D    E
2  1.0  1.0  1.0  1.0
3  1.0  1.0  1.0  1.0
4  1.0  1.0  1.0  1.0

join行往外合并:相当于全连接
     A    B    C    D    B    C    D    E
1  0.0  0.0  0.0  0.0  NaN  NaN  NaN  NaN
2  0.0  0.0  0.0  0.0  1.0  1.0  1.0  1.0
3  0.0  0.0  0.0  0.0  1.0  1.0  1.0  1.0
4  NaN  NaN  NaN  NaN  1.0  1.0  1.0  1.0

join行相同的进行合并:相当于内连接
     A    B    C    D    B    C    D    E
2  0.0  0.0  0.0  0.0  1.0  1.0  1.0  1.0
3  0.0  0.0  0.0  0.0  1.0  1.0  1.0  1.0

以df1的序列进行合并:相当于左连接
     A    B    C    D    B    C    D    E
1  0.0  0.0  0.0  0.0  NaN  NaN  NaN  NaN
2  0.0  0.0  0.0  0.0  1.0  1.0  1.0  1.0
3  0.0  0.0  0.0  0.0  1.0  1.0  1.0  1.0
复制代码
append添加数据

复制代码
import numpy as np
import pandas as pd
 
df1=pd.DataFrame(np.ones((3,4))*0,columns=['a','b','c','d'])
df2=pd.DataFrame(np.ones((3,4))*1,columns=['a','b','c','d'])
df3=pd.DataFrame(np.ones((3,4))*2,columns=['a','b','c','d'])
s1=pd.Series([1,2,3,4],index=['a','b','c','d'])
 
print('将df2合并到df1的下面 并重置index')
res=df1.append(df2,ignore_index=True)
print(res)
print('\n')
 
print('将s1合并到df1的下面,并重置index')
res2=df1.append(s1,ignore_index=True)
print(res2)
 
----------执行以上程序,返回的结果为----------
将df2合并到df1的下面 并重置index
     a    b    c    d
0  0.0  0.0  0.0  0.0
1  0.0  0.0  0.0  0.0
2  0.0  0.0  0.0  0.0
3  1.0  1.0  1.0  1.0
4  1.0  1.0  1.0  1.0
5  1.0  1.0  1.0  1.0

将s1合并到df1的下面,并重置index
     a    b    c    d
0  0.0  0.0  0.0  0.0
1  0.0  0.0  0.0  0.0
2  0.0  0.0  0.0  0.0
3  1.0  2.0  3.0  4.0
复制代码
10.Pandas合并merge
依据一组key合并

复制代码
import numpy as np
import pandas as pd
 
left=pd.DataFrame({'key':['k0','k1','k2','k3'],
                     'A':['A0','A1','A2','A3'],
                     'B':['B0','B1','B2','B3']})
print('第一个数据为:')
print(left)
print('\n')
 
right=pd.DataFrame({'key':['k0','k1','k2','k3'],
                      'C':['C0','C1','C2','C3'],
                      'D':['D0','D1','D2','D3']})
print('第二个数据为:')
print(right)
print('\n')
 
print('依据key进行merge:')
res=pd.merge(left,right,on='key')
print(res)
 
----------执行以上程序,返回的结果为----------
第一个数据为:
  key   A   B
0  k0  A0  B0
1  k1  A1  B1
2  k2  A2  B2
3  k3  A3  B3

第二个数据为:
  key   C   D
0  k0  C0  D0
1  k1  C1  D1
2  k2  C2  D2
3  k3  C3  D3

依据key进行merge:
  key   A   B   C   D
0  k0  A0  B0  C0  D0
1  k1  A1  B1  C1  D1
2  k2  A2  B2  C2  D2
3  k3  A3  B3  C3  D3
复制代码
依据两组key合并

复制代码
import numpy as np
import pandas as pd
 
left=pd.DataFrame({'key1':['k0','k1','k2','k3'],
                   'key2':['k0','k1','k0','k1'],
                      'A':['A0','A1','A2','A3'],
                      'B':['B0','B1','B2','B3']})
print('第一个数据为:')
print(left)
print('\n')
 
right=pd.DataFrame({'key1':['k0','k1','k2','k3'],
                    'key2':['k0','k0','k0','k0'],
                       'C':['C0','C1','C2','C3'],
                       'D':['D0','D1','D2','D3']})
print('第二个数据为:')
print(right)
print('\n')
 
print('内联合并')
res=pd.merge(left,right,on=['key1','key2'],how='inner')
print(res)
print('\n')
 
print('外联合并')
res2=pd.merge(left,right,on=['key1','key2'],how='outer')
print(res2)
print('\n')
 
print('左联合并')
res3=pd.merge(left,right,on=['key1','key2'],how='left')
print(res3)
print('\n')
 
print('右联合并')
res4=pd.merge(left,right,on=['key1','key2'],how='right')
print(res4)
 
----------执行以上程序,返回的结果为----------
第一个数据为:
  key1 key2   A   B
0   k0   k0  A0  B0
1   k1   k1  A1  B1
2   k2   k0  A2  B2
3   k3   k1  A3  B3

第二个数据为:
  key1 key2   C   D
0   k0   k0  C0  D0
1   k1   k0  C1  D1
2   k2   k0  C2  D2
3   k3   k0  C3  D3

内联合并
  key1 key2   A   B   C   D
0   k0   k0  A0  B0  C0  D0
1   k2   k0  A2  B2  C2  D2

外联合并
  key1 key2    A    B    C    D
0   k0   k0   A0   B0   C0   D0
1   k1   k1   A1   B1  NaN  NaN
2   k2   k0   A2   B2   C2   D2
3   k3   k1   A3   B3  NaN  NaN
4   k1   k0  NaN  NaN   C1   D1
5   k3   k0  NaN  NaN   C3   D3

左联合并
  key1 key2   A   B    C    D
0   k0   k0  A0  B0   C0   D0
1   k1   k1  A1  B1  NaN  NaN
2   k2   k0  A2  B2   C2   D2
3   k3   k1  A3  B3  NaN  NaN

右联合并
  key1 key2    A    B   C   D
0   k0   k0   A0   B0  C0  D0
1   k2   k0   A2   B2  C2  D2
2   k1   k0  NaN  NaN  C1  D1
3   k3   k0  NaN  NaN  C3  D3
复制代码
Indicator合并

复制代码
import numpy as np
import pandas as pd
df1=pd.DataFrame({'col1':[0,1],'col_left':['a','b']})
df2=pd.DataFrame({'col1':[1,2,2],'col_right':[2,2,2]})
print('第一个数据为:')
print(df1)
print('\n')
 
print('第二个数据为:')
print(df2)
print('\n')
 
print('依据col1进行合并 并启用indicator=True输出每项合并方式:')
res=pd.merge(df1,df2,on='col1',how='outer',indicator=True)
print(res)
print('\n')
 
----------执行以上程序,返回的结果为----------
第一个数据为:
   col1 col_left
0     0        a
1     1        b

第二个数据为:
   col1  col_right
0     1          2
1     2          2
2     2          2

依据col1进行合并 并启用indicator=True输出每项合并方式:
   col1 col_left  col_right      _merge
0     0        a        NaN   left_only
1     1        b        2.0        both
2     2      NaN        2.0  right_only
3     2      NaN        2.0  right_only
 
复制代码
依据index合并

复制代码
import numpy as np
import pandas as pd
 
left=pd.DataFrame({'A':['A0','A1','A2'],
                   'B':['B0','B1','B2']},
                   index=['k0','k1','k2'])
 
right=pd.DataFrame({'C':['C0','C1','C2'],
                    'D':['D0','D1','D2']},
                   index=['k0','k2','k3']
)
 
print('第一个数据为:')
print(left)
print('\n')
 
print('第二个数据为:')
print(right)
print('\n')
 
print('根据index索引进行合并 并选择外联合并')
res=pd.merge(left,right,left_index=True,right_index=True,how='outer')
print(res)
print('\n')
 
print('根据index索引进行合并 并选择内联合并')
res2=pd.merge(left,right,left_index=True,right_index=True,how='inner')
print(res2)
print('\n')
 
 
----------执行以上程序,返回的结果为----------
第一个数据为:
     A   B
k0  A0  B0
k1  A1  B1
k2  A2  B2

第二个数据为:
     C   D
k0  C0  D0
k2  C1  D1
k3  C2  D2

根据index索引进行合并 并选择外联合并
      A    B    C    D
k0   A0   B0   C0   D0
k1   A1   B1  NaN  NaN
k2   A2   B2   C1   D1
k3  NaN  NaN   C2   D2

根据index索引进行合并 并选择内联合并
     A   B   C   D
k0  A0  B0  C0  D0
k2  A2  B2  C1  D1

本文主要是对pandas进行入门详细介绍,通过本文你将系统性了解pandas为何会有数据分析界"瑞士军刀"的盛誉。

img

行文二级目录


01 关于pandas

img

pandas,python+data+analysis的组合缩写,是python中基于numpy和matplotlib的第三方数据分析库,与后两者共同构成了python数据分析的基础工具包,享有数分三剑客之名。

正因为pandas是在numpy基础上实现,其核心数据结构与numpy的ndarray十分相似,但pandas与numpy的关系不是替代,而是互为补充。二者之间主要区别是:

  • 从数据结构上看:
    • numpy的核心数据结构是ndarray,支持任意维数的数组,但要求单个数组内所有数据是同质的,即类型必须相同;而pandas的核心数据结构是series和dataframe,仅支持一维和二维数据,但数据内部可以是异构数据,仅要求同列数据类型一致即可
    • numpy的数据结构仅支持数字索引,而pandas数据结构则同时支持数字索引和标签索引
  • 从功能定位上看:
    • numpy虽然也支持字符串等其他数据类型,但仍然主要是用于数值计算,尤其是内部集成了大量矩阵计算模块,例如基本的矩阵运算、线性代数、fft、生成随机数等,支持灵活的广播机制
    • pandas主要用于数据处理与分析,支持包括数据读写、数值计算、数据处理、数据分析和数据可视化全套流程操作

pandas主要面向数据处理与分析,主要具有以下功能特色:

  • 按索引匹配的广播机制,这里的广播机制与numpy广播机制还有很大不同
  • 便捷的数据读写操作,相比于numpy仅支持数字索引,pandas的两种数据结构均支持标签索引,包括bool索引也是支持的
  • 类比SQL的join和groupby功能,pandas可以很容易实现SQL这两个核心功能,实际上,SQL的绝大部分DQL和DML操作在pandas中都可以实现
  • 类比Excel的数据透视表功能,Excel中最为强大的数据分析工具之一是数据透视表,这在pandas中也可轻松实现
  • 自带正则表达式的字符串向量化操作,对pandas中的一列字符串进行通函数操作,而且自带正则表达式的大部分接口
  • 丰富的时间序列向量化处理接口
  • 常用的数据分析与统计功能,包括基本统计量、分组统计分析等
  • 集成matplotlib的常用可视化接口,无论是series还是dataframe,均支持面向对象的绘图接口

正是由于具有这些强大的数据分析与处理能力,pandas还有数据处理中"瑞士军刀"的美名。

02 数据结构

img

pandas核心数据结构有两种,即一维的series和二维的dataframe,二者可以分别看做是在numpy一维数组和二维数组的基础上增加了相应的标签信息。正因如此,可以从两个角度理解series和dataframe:

  • series和dataframe分别是一维和二维数组,因为是数组,所以numpy中关于数组的用法基本可以直接应用到这两个数据结构,包括数据创建、切片访问、通函数、广播机制等
  • series是带标签的一维数组,所以还可以看做是类字典结构:标签是key,取值是value;而dataframe则可以看做是嵌套字典结构,其中列名是key,每一列的series是value。所以从这个角度讲,pandas数据创建的一种灵活方式就是通过字典或者嵌套字典,同时也自然衍生出了适用于series和dataframe的类似字典访问的接口,即通过loc索引访问。

注意,这里强调series和dataframe是一个类字典结构而非真正意义上的字典,原因在于series中允许标签名重复、dataframe中则允许列名和标签名均有重复,而这是一个真正字典所不允许的。

考虑series和dataframe兼具numpy数组和字典的特性,那么就不难理解二者的以下属性:

  • ndim/shape/dtypes/size/T,分别表示了数据的维数、形状、数据类型和元素个数以及转置结果。其中,由于pandas允许数据类型是异构的,各列之间可能含有多种不同的数据类型,所以dtype取其复数形式dtypes。与此同时,series因为只有一列,所以数据类型自然也就只有一种,pandas为了兼容二者,series的数据类型属性既可以用dtype也可以用dtypes获取;而dataframe则只能用dtypes。
  • index/columns/values,分别对应了行标签、列标签和数据,其中数据就是一个格式向上兼容所有列数据类型的array。为了沿袭字典中的访问习惯,还可以用keys()访问标签信息,在series返回index标签,在dataframe中则返回columns列名;可以用items()访问键值对,但一般用处不大。

这里提到了index和columns分别代表行标签和列标签,就不得不提到pandas中的另一个数据结构:Index,例如series中标签列、dataframe中行标签和列标签均属于这种数据结构。既然是数据结构,就必然有数据类型dtype属性,例如数值型、字符串型或时间类型等,其类型绝大多数场合并不是我们关注的主体,但有些时候值得注意,如后文中提到的通过[ ]执行标签切片访问行的过程。此外,index数据结构还有名字属性name(默认为None)、形状属性shape等。

img

关于series和dataframe数据结构本身,有大量的方法可用于重构结构信息:

  • rename,可以对标签名重命名,也可以重置index和columns的部分标签列信息,接收标量(用于对标签名重命名)或字典(用于重命名行标签和列标签)
  • reindex,接收一个新的序列与已有标签列匹配,当原标签列中不存在相应信息时,填充NAN或者可选的填充值
  • set_index/reset_index,互为逆操作,前者是将已有的一列信息设置为标签列,而后者是将原标签列归为数据,并重置为默认数字标签
  • set_axis,设置标签列,一次只能设置一列信息,与rename功能相近,但接收参数为一个序列更改全部标签列信息(rename中是接收字典,允许只更改部分信息)
  • rename_axis,重命名标签名,rename中也可实现相同功能

img

在pandas早些版本中,除一维数据结构series和二维数据结构dataframe外,还支持三维数据结构panel。这三者是构成递进包容关系,panel即是dataframe的容器,用于存储多个dataframe。2019年7月,随着pandas 0.25版本的推出,pandas团队宣布正式弃用panel数据结构,而相应功能建议由多层索引实现。

也正因为pandas这3种独特的数据结构,个人一度认为pandas包名解释为:pandas = panel + dataframe + series,根据维数取相应的首字母个数,从而构成pandas,这是个人非常喜欢的一种关于pandas缩写的解释。

03 数据读写

img

pandas支持大部分的主流文件格式进行数据读写,常用格式及接口为:

  • 文本文件,主要包括csv和txt两种等,相应接口为read_csv()和to_csv(),分别用于读写数据
  • Excel文件,包括xls和xlsx两种格式均得到支持,底层是调用了xlwt和xlrd进行excel文件操作,相应接口为read_excel()和to_excel()
  • SQL文件,支持大部分主流关系型数据库,例如MySQL,需要相应的数据库模块支持,相应接口为read_sql()和to_sql()

此外,pandas还支持html、json等文件格式的读写操作。

04 数据访问

img

series和dataframe兼具numpy数组和字典的结构特性,所以数据访问都是从这两方面入手。同时,也支持bool索引进行数据访问和筛选。

  • [ ],这是一个非常便捷的访问方式,不过需区分series和dataframe两种数据结构理解:
    • series:既可以用标签也可以用数字索引访问单个元素,还可以用相应的切片访问多个值,因为只有一维信息,自然毫无悬念
    • dataframe:无法访问单个元素,只能返回一列、多列或多行:单值或多值(多个列名组成的列表)访问时按列进行查询,单值访问不存在列名歧义时还可直接用属性符号" . "访问。切片形式访问时按行进行查询,又区分数字切片和标签切片两种情况:当输入数字索引切片时,类似于普通列表切片;当输入标签切片时,执行范围查询(即无需切片首末值存在于标签列中),包含两端标签结果,无匹配行时返回为空,但要求标签切片类型与索引类型一致。例如,当标签列类型(可通过df.index.dtype查看)为时间类型时,若使用无法隐式转换为时间的字符串作为索引切片,则引发报错

img

切片形式返回行查询,且为范围查询

img

切片类型与索引列类型不一致时,引发报错

  • loc/iloc,最为常用的两种数据访问方法,其中loc按标签值访问、iloc按数字索引访问,均支持单值访问或切片查询。与[ ]访问类似,loc按标签访问时也是执行范围查询,包含两端结果
  • at/iat,loc和iloc的特殊形式,不支持切片访问,仅可以用单个标签值或单个索引值进行访问,一般返回标量结果,除非标签值存在重复
  • isin/notin,条件范围查询,即根据特定列值是否存在于指定列表返回相应的结果
  • where,仍然是执行条件查询,但会返回全部结果,只是将不满足匹配条件的结果赋值为NaN或其他指定值,可用于筛选或屏蔽值

img

  • query,按列对dataframe执行条件查询,一般可用常规的条件查询替代

img

  • get,由于series和dataframe均可以看做是类字典结构,所以也可使用字典中的get()方法,主要适用于不确定数据结构中是否包含该标签时,与字典的get方法完全一致

img

  • lookup,loc的一种特殊形式,分别传入一组行标签和列标签,lookup解析成一组行列坐标,返回相应结果:

img

pandas中支持大量的数据访问接口,但万变不离其宗:只要联想两种数据结构兼具numpy数组和字典的双重特性,就不难理解这些数据访问的逻辑原理。当然,重点还是掌握[]、loc和iloc三种方法。

loc和iloc应该理解为是series和dataframe的属性而非函数,应用loc和iloc进行数据访问就是根据属性值访问的过程

另外,在pandas早些版本中,还存在loc和iloc的兼容结构,即ix,可混合使用标签和数字索引,但往往容易混乱,所以现已弃用

05 数据处理

img

pandas最为强大的功能当然是数据处理和分析,可独立完成数据分析前的绝大部分数据预处理需求。简单归纳来看,主要可分为以下几个方面:

1

数据清洗

数据处理中的清洗工作主要包括对空值、重复值和异常值的处理:

  • 空值
    • 判断空值,isna或isnull,二者等价,用于判断一个series或dataframe各元素值是否为空的bool结果。需注意对空值的界定:即None或numpy.nan才算空值,而空字符串、空列表等则不属于空值;类似地,notna和notnull则用于判断是否非空
    • 填充空值,fillna,按一定策略对空值进行填充,如常数填充、向前/向后填充等,也可通过inplace参数确定是否本地更改
    • 删除空值,dropna,删除存在空值的整行或整列,可通过axis设置,也包括inplace参数
  • 重复值
    • 检测重复值,duplicated,检测各行是否重复,返回一个行索引的bool结果,可通过keep参数设置保留第一行/最后一行/无保留,例如keep=first意味着在存在重复的多行时,首行被认为是合法的而可以保留
    • 删除重复值,drop_duplicates,按行检测并删除重复的记录,也可通过keep参数设置保留项。由于该方法默认是按行进行检测,如果存在某个需要需要按列删除,则可以先转置再执行该方法
  • 异常值,判断异常值的标准依赖具体分析数据,所以这里仅给出两种处理异常值的可选方法
    • 删除,drop,接受参数在特定轴线执行删除一条或多条记录,可通过axis参数设置是按行删除还是按列删除
    • 替换,replace,非常强大的功能,对series或dataframe中每个元素执行按条件替换操作,还可开启正则表达式功能

2

数值计算

由于pandas是在numpy的基础上实现的,所以numpy的常用数值计算操作在pandas中也适用:

  • 通函数ufunc,即可以像操作标量一样对series或dataframe中的所有元素执行同一操作,这与numpy的特性是一致的,例如前文提到的replace函数,本质上可算作是通函数。如下实现对数据表中逐元素求平方

img

  • 广播机制,即当维度或形状不匹配时,会按一定条件广播后计算。由于pandas是带标签的数组,所以在广播过程中会自动按标签匹配进行广播,而非类似numpy那种纯粹按顺序进行广播。例如,如下示例中执行一个dataframe和series相乘,虽然二者维度不等、大小不等、标签顺序也不一致,但仍能按标签匹配得到预期结果

img

  • 字符串向量化,即对于数据类型为字符串格式的一列执行向量化的字符串操作,本质上是调用series.str属性的系列接口,完成相应的字符串操作。尤为强大的是,除了常用的字符串操作方法,str属性接口中还集成了正则表达式的大部分功能,这使得pandas在处理字符串列时,兼具高效和强力。例如如下代码可用于统计每个句子中单词的个数

img

需注意的是,这里的字符串接口与python中普通字符串的接口形式上很是相近,但二者是不一样的。

  • 时间类型向量化操作,如字符串一样,在pandas中另一个得到"优待"的数据类型是时间类型,正如字符串列可用str属性调用字符串接口一样,时间类型列可用dt属性调用相应接口,这在处理时间类型时会十分有效。

img

3

数据转换

前文提到,在处理特定值时可用replace对每个元素执行相同的操作,然而replace一般仅能用于简单的替换操作,所以pandas还提供了更为强大的数据转换方法

  • map,适用于series对象,功能与python中的普通map函数类似,即对给定序列中的每个值执行相同的映射操作,不同的是series中的map接口的映射方式既可以是一个函数,也可以是一个字典

img

  • apply,既适用于series对象也适用于dataframe对象,但对二者处理的粒度是不一样的:apply应用于series时是逐元素执行函数操作;apply应用于dataframe时是逐行或者逐列执行函数操作(通过axis参数设置对行还是对列,默认是行),仅接收函数作为参数

img

  • applymap,仅适用于dataframe对象,且是对dataframe中的每个元素执行函数操作,从这个角度讲,与replace类似,applymap可看作是dataframe对象的通函数。

img

4

合并与拼接

pandas中又一个重量级数据处理功能是对多个dataframe进行合并与拼接,对应SQL中两个非常重要的操作:union和join。pandas完成这两个功能主要依赖以下函数:

  • concat,与numpy中的concatenate类似,但功能更为强大,可通过一个axis参数设置是横向或者拼接,要求非拼接轴向标签唯一(例如沿着行进行拼接时,要求每个df内部列名是唯一的,但两个df间可以重复,毕竟有相同列才有拼接的实际意义)
  • merge,完全类似于SQL中的join语法,仅支持横向拼接,通过设置连接字段,实现对同一记录的不同列信息连接,支持inner、left、right和outer4种连接方式,但只能实现SQL中的等值连接
  • join,语法和功能与merge一致,不同的是merge既可以用pandas接口调用,也可以用dataframe对象接口调用,而join则只适用于dataframe对象接口
  • append,concat执行axis=0时的一个简化接口,类似列表的append函数一样

实际上,concat通过设置axis=1也可实现与merge类似的效果,二者的区别在于:merge允许连接字段重复,类似一对多或者多对一连接,此时将产生笛卡尔积结果;而concat则不允许重复,仅能一对一拼接。

img

建表语句

img

通过设置参数,concat和merge实现相同效果

06 数据分析

img

pandas中的另一大类功能是数据分析,通过丰富的接口,可实现大量的统计需求,包括Excel和SQL中的大部分分析过程,在pandas中均可以实现。

1

基本统计量

pandas内置了丰富的统计接口,这是与numpy是一致的,同时又包括一些常用统计信息的集成接口。

  • info,展示行标签、列标签、以及各列基本信息,包括元素个数和非空个数及数据类型等
  • head/tail,从头/尾抽样指定条数记录
  • describe,展示数据的基本统计指标,包括计数、均值、方差、4分位数等,还可接收一个百分位参数列表展示更多信息

img

  • count、value_counts,前者既适用于series也适用于dataframe,用于按列统计个数,实现忽略空值后的计数;而value_counts则仅适用于series,执行分组统计,并默认按频数高低执行降序排列,在统计分析中很有用

img

  • unique、nunique,也是仅适用于series对象,统计唯一值信息,前者返回唯一值结果列表,后者返回唯一值个数(number of unique)

img

  • sort_index、sort_values,既适用于series也适用于dataframe,sort_index是对标签列执行排序,如果是dataframe可通过axis参数设置是对行标签还是列标签执行排序;sort_values是按值排序,如果是dataframe对象,也可通过axis参数设置排序方向是行还是列,同时根据by参数传入指定的行或者列,可传入多行或多列并分别设置升序降序参数,非常灵活。另外,在标签列已经命名的情况下,sort_values可通过by标签名实现与sort_index相同的效果。

img

2

分组聚合

pandas的另一个强大的数据分析功能是分组聚合以及数据透视表,前者堪比SQL中的groupby,后者媲美Excel中的数据透视表。

  • groupby,类比SQL中的group by功能,即按某一列或多列执行分组。一般而言,分组的目的是为了后续的聚合统计,所有groupby函数一般不单独使用,而需要级联其他聚合函数共同完成特定需求,例如分组求和、分组求均值等。

img

pandas官网关于groupby过程的解释

级联其他聚合函数的方式一般有两种:单一的聚合需求用groupby+聚合函数即可,复杂的大量聚合则可借用agg函数,agg函数接受多种参数形式作为聚合函数,功能更为强大。

img

两种分组聚合形式

  • pivot,pivot英文有"支点"或者"旋转"的意思,排序算法中经典的快速排序就是不断根据pivot不断将数据二分,从而加速排序过程。用在这里,实际上就是执行行列重整。例如,以某列取值为重整后行标签,以另一列取值作为重整后的列标签,以其他列取值作为填充value,即实现了数据表的行列重整。以SQL中经典的学生成绩表为例,给定原始学生—课程—成绩表,需重整为学生vs课程的成绩表,则可应用pivot实现:

img

另外,还有一对函数也常用于数据重整,即stack和unstack,其中unstack执行效果与pivot非常类似,而stack则是unstack的逆过程。

  • pivot_table,有了pivot就不难理解pivot_table,实际上它是在前者的基础上增加了聚合的过程,类似于Excel中的数据透视表功能。仍然考虑前述学生成绩表的例子,但是再增加一列班级信息,需求是统计各班级每门课程的平均分。由于此时各班的每门课成绩信息不唯一,所以直接用pivot进行重整会报错,此时即需要对各班各门课程成绩进行聚合后重整,比如取平均分。

img

07 数据可视化

img

pandas集成了matplotlib中的常用可视化图形接口,可通过series和dataframe两种数据结构面向对象的接口方式简单调用。关于面向对象接口和plt接口绘图方式的区别,可参考python数据科学系列:matplotlib入门详细教程

两种数据结构作图,区别仅在于series是绘制单个图形,而dataframe则是绘制一组图形,且在dataframe绘图结果中以列名为标签自动添加legend。另外,均支持两种形式的绘图接口:

  • plot属性+相应绘图接口,如plot.bar()用于绘制条形图
  • plot()方法并通过传入kind参数选择相应绘图类型,如plot(kind='bar')

img

不过,pandas绘图中仅集成了常用的图表接口,更多复杂的绘图需求往往还需依赖matplotlib或者其他可视化库

posted @ 2021-05-16 21:59  mjth  阅读(84)  评论(0)    收藏  举报