pandas的基本使用
pandas是一种Python数据分析的利器,是一个开源的数据分析包, 最初是应用于金融数据分析工具而开发出来的,因此pandas为时间 序列分析提供了很好的支持。pandas是PyData项目的一部分。
官方文档:https://pandas.pydata.org/pandas-docs/stable/
安装过程详见: 官方安装文档。
Python版本要求:2.7、3.4、3.5、3.。
依赖Python库:setuptools、NumPy、python-dateutil、pytz。
安装方式:
Python的Anaconda发行版,已经安装好pandas库,不需要另外安装。
使用Anaconda界面安装,选择对应的pandas进行勾选安装即可。
使用Anaconda命令安装:conda install pandas。
使用PyPi安装命令安装:pip install pandas
引入约定:from pandas import Series, DataFrame或import pandas as pd
pandas基本数据结构
pandas中主要有两种数据结构,分别是:Series和DataFrame。
Series:一种类似于一维数组的对象,是由一组数据(各种NumPy数 据类型)以及一组与之相关的数据标签(即索引)组成。仅由一组数据也 可产生简单的Series对象。注意:Series中的索引值是可以重复的。
DataFrame:一个表格型的数据结构,包含有一组有序的列,每列 可以是不同的值类型(数值、字符串、布尔型等),DataFrame即有行 索引也有列索引,可以被看做是由Series组成的字典。
Series数据结构
通过一维数组创建Series


通过字典创建Series

import pandas as pd import numpy as np ''' 使用列表创建 ''' ser01 = pd.Series([1,2,3,4]) ''' 使用数组创建 ''' ser02 = pd.Series(np.random.randint(1,9,5)) ''' 使用字典创建Series ''' dic = { 'a':1, 'b':2, 'c':3 } ser03 = pd.Series(dic) print(ser03.index) print(ser03.values) print(ser03.dtype) ''' 设置index ''' # 修改index的值 ser02.index = list('abcde') print(ser02) #创建时 制定 index ser05 = pd.Series(np.random.randint(1,9,5),index = ['a','b','c','d','e']) print(ser05)
Series常见属性
import pandas as pd import numpy as np ''' 常见属性 ''' ser02 = pd.Series(np.random.randint(1,9,5),index = ['a','b','c','d','e']) ser02.name = '帅哥' ser02.index.name = '编号' # print('数据标题:{}'.format(ser02.name)) # print('数据行索引的标题:{}'.format(ser02.index.name)) # print('行轴标签列表:{}'.format(ser02.axes)) # print('对象的数据类型:{}'.format(ser02.dtype)) # print('对象是否为空:{}'.format(ser02.empty)) # print('Series对象的行索引:{}'.format(ser02.index)) # print('Series对象底层数据的维度数:{}'.format(ser02.ndim)) # print('Series对象的元素个数:{}'.format(ser02.size)) # print('Series对象作为ndarray数组返回:',ser02.values,sep='\n') # print('返回Series对象的前n行:',ser02.head(3),sep='\n') # print('返回Series对象的后n行:',ser02.tail(3),sep='\n')
Series值得获取
Series值的获取主要有两种方式:
通过方括号+索引的方式读取对应索引的数据,有可能返回多条数据。
通过方括号+下标值的方式读取对应下标值的数据,下标值的取值范围为: [0,len(Series.values));另外下标值也可以是负数,表示从右往左获取数据。
Series切片
Series获取多个值的方式类似NumPy中的ndarray的切片操作,通 过方括号+下标值/索引值+冒号(:)的形式来截取series对象中的一部 分数。
import pandas as pd import numpy as np np.random.seed(28) ser02 = pd.Series(np.random.randint(1,9,5),index = ['a','b','c','d','e']) # 通过索引获取 print(ser02['a']) #通过数字下标获取 print(ser02[0]) print(ser02[-1]) # 获取多个元素 print(ser02[['a','c']]) # 切片 print(ser02['a':'c']) print(type(ser02['a':'c'])) # 具有相同索引, 不能通过下标获取。 ser = pd.Series(np.random.randint(1,9,5),index = ['a','b','b','d','e']) print(ser['b']) # print(ser[0]) #会报错
series的运算
NumPy中的数组运算,在Series中都保留了,均可以使用,并且 Series进行数组运算的时候,索引与值之间的映射关系不会发生改变。
注意:其实在操作Series的时候,基本上可以把Series看成NumPy 中的ndarray数组来进行操作。ndarray数组的绝大多数操作都可以 应用到Series上。
import pandas as pd import numpy as np ser01 = pd.Series(np.random.randint(1,5,5)) # 与标量进行运算 # print(ser01+10) # print(ser01-10) # print(ser01*10) # print(ser01/10) # print(ser01**2) # series 与 series 的运算 print(ser01) ser02 = pd.Series(np.random.randint(1,5,5)) print(ser02) # print(ser01+ser02) # print(ser01-ser02) # print(ser01*ser02) # print(ser01/ser02) # print(ser01**ser02) # 直接使用numpy的通用函数 # print(np.log(ser01)) # print(np.exp(ser01)) # print(ser01[ser01<4]) # print(ser01<4)
Series自动对齐
当多个series对象之间进行运算的时候,如果不同series之间具有不 同的索引值,那么运算会自动对齐相同索引值的数据,如果某个 series没有某个索引值,那么最终结果会赋值为NaN。
import pandas as pd import numpy as np ser01 = pd.Series(np.random.randint(1,5,5),index = list('abcde')) print(ser01) ser02 = pd.Series(np.random.randint(1,5,5),index = list('abmne')) print(ser02) mask = ser01+ser02 # 对于无法通过下标对应的数据 被重新赋值为NaN print(mask)
Series缺失值检测
pandas中的isnull和notnull两个函数可以用于在Series中检测缺失 值,这两个函数的返回时一个布尔类型的Series。
import pandas as pd import numpy as np ser01 = pd.Series(np.random.randint(1,5,5),index = list('abcde')) ser01['b'] = np.NaN ser01['e'] = np.NaN print(ser01) print(ser01.isnull() ) # 返回一个bool series print(ser01[~ser01.isnull()] ) # 过滤缺失值 print(ser01.notnull()) print(ser01[ser01.notnull()] ) # 过滤缺失值 # 结合numpy 函数过滤NaN数据 print(np.isnan(ser01)) print(ser01[~np.isnan(ser01)] )
DataFrame数据帧

通过二维数组创建Dataframe

通过字典的方式创建Dataframe

索引对象与DataFrame数据获取
索引对象
不管是Series还是DataFrame对象,都有索引对象。 索引对象负责管理轴标签和其它元数据(eg:轴名称等等)。
通过索引可以从Series、DataFrame中获取值或者对某个索引值进行重新赋值。
Series或者DataFrame的自动对齐功能是通过索引实现的。
import pandas as pd import numpy as np ''' 通过列表创建 ''' li = [[1,2,3,4],[5,6,7,8]] df01 = pd.DataFrame(li) # print(df01.shape) #查看数据形状 # print(df01.ndim) # print(df01.dtypes) #查看数据类型 # print(df01.index) #查看行索引 # print(df01.columns) #查看列索引 # print('返回数据的ndarray形式:',df01.values,sep='\n') ''' 通过series创建 ''' ser01 = pd.Series([1,2,3,4]) ser02 = pd.Series([1,2,3,4]) df02 = pd.DataFrame([ser01,ser02]) ''' 数组创建 ''' arr = np.random.randint(1,9,(3,3)) df03 = pd.DataFrame(arr) ''' 字典创建 ''' dic = { 'name':['joe','anne','yilianna'], # key 就是 列索引 'age':[18,19,20], 'class':1 # 要求字典的value必须是长度相等的序列或是一个标量 } df04 = pd.DataFrame(dic,index=['一班','二班','三班']) #自定义索引值 print(df04) # print('行索引:{}'.format(df04.index)) # print('列索引:{}'.format(df04.columns)) # print('数据:',df04.values,sep='\n') ''' 重置索引 ''' # df04.index = list('abc') # df04.index.name = 'index' #行索引的标题 # df04.columns.name = 'info'#列索引的标题 # print(df04) #删除索引 # print(df04.reset_index(drop=True)) # print(df04) ''' 设置某一列为行索引 ''' df04 = df04.set_index('name') print(df04.axes) #查看行和列的索引标签 print(df04) ''' 重置列索引 ''' df04.columns = list('AB') print(df04)
DataFrame数据获取
可以直接通过列索引获取指定列的数据, eg: df[column_name],取某个值:df[column_name,index_name]
如果需要获取指定行的数据的话,需要通过ix方法来获取对应行索引 的行数据,eg: df.ix[index_name]、loc、iloc。取某个值:df.ix[index_name,column_name]
import pandas as pd import numpy as np ''' 通过列表创建 ''' li = [[1,2,3,4],[5,6,7,8]] df = pd.DataFrame(li) df.index.name = 'index_name' df.columns.name = 'columns_name' print(df) #获取列 # print(df[1]) #列切片 # df.columns = list('abcd') # print(df[df.columns[0:2]]) #只能用下标切片 #获取行 # print(df.loc[1]) # print(df.iloc[1]) # print(df.ix[1]) #行切片 # print(df.loc[0:2]) print(df.loc[0:1,0:1]) #左闭右闭 #获取某个值 print(df.loc[0,1]) print(df.loc[1,0])
DataFrame数据的增删改查
import pandas as pd import numpy as np ''' 列操作 查 ''' dic = { 'name':['joe','anne','yilianna'], # key 就是 列索引 'age':[18,19,20], 'class':1 # 整列数据会被标量填充 } df03 = pd.DataFrame(dic) print(df03['name'] ) # 返回一个series # 获取多列数据 print(df03[['name','age']]) # 当获取多列数据的时候返回DataFrame ''' 增 ''' df03['address'] = ['usa','uk','chn'] # 添加不存在的列索引 print(df03) ''' 删 ''' df03.pop('address') # 返回被删除的内容 # del(df03['address']) # del 删除 ''' 改 ''' df03['class'] = [3,4,5] ''' 行操作 查 ''' print(df03.loc[0]) # 获取多行数据 print(df03.loc[[0,2]]) # 选择某行某列 print(df03.loc[0,'name']) print(df03.loc[[0,2],'name']) print(df03.loc[[0,2],['name','age']]) # 切片 print(df03.loc[1:,'class':'name']) df03.index = ['a','b','c'] print(df03.iloc[0] ) # 可以使用数字索引获取 print(df03.iloc[[0,1],[0,1]]) ''' 增 ''' df03.loc['d'] = [16,6,'ronaldo'] # 指定一个不存在的行索引 对应上每一列数据 print(df03) ''' 删 ''' df03 = df03.drop('d') ''' 改 ''' df03.loc['c'] = [18,9,'messi']
pandas基本功能
数据文件读取/存储
通过pandas提供的read_xxx相关的函数可以读取文件中的数据,并 形成DataFrame,常用的数据读取方法为:read_csv,主要可以读取 文本类型的数据。
读/写数据库
import pandas as pd import numpy as np import sqlalchemy from sqlalchemy import create_engine from faker import Factory import random engine = create_engine('mysql+pymysql://user:password@ip:port/database_name?charset=utf8') columns_name = ['name','age','sex','phone_number'] fake = Factory().create('ZH_cn') sex = [random.choice(['男','女']) for k in range(5)] name = [fake.name_male() if i == '男' else fake.name_female() for i in sex] age = [random.choice([21,19,22,18,20]) for e in range(5)] phone_number = [fake.phone_number() for j in range(5)] data = np.array([name,age,sex,phone_number]).T df = pd.DataFrame(data,columns=columns_name) table_name = 'test_datas' ''' name : string 表名 con : sqlalchemy.engine.Engine or sqlite3.Connection 一个SQLAlchemy的连接数据库的对象 schema : string, optional 指定架构(如果数据库flavor支持此)。如果为None,请使用默认架构。 if_exists : {'fail', 'replace', 'append'}, default 'fail' 如果表已存在,如何表现。 fail:引发ValueError。 replace:在插入新值之前删除表。 append:将新值插入现有表。 index : bool, default True 将DataFrame索引写为列。使用index_label作为表中的列名。 index_label : string or sequence, default None 索引列的列标签。如果给出None(默认)且 index为True,则使用索引名称。如果DataFrame使用MultiIndex,则应该给出一个序列。 chunksize : int, optional 行将一次批量写入此大小。默认情况下,所有行都将立即写入。 dtype : dict, optional 指定列的数据类型。键应该是列名,值应该是SQLAlchemy类型或sqlite3传统模式的字符串。 ''' df.to_sql(table_name,engine,if_exists='append',index=False, dtype={ 'name':sqlalchemy.types.String(10), 'age':sqlalchemy.types.Integer(), 'sex':sqlalchemy.types.String(3), 'phone_number':sqlalchemy.types.BigInteger() } ) print(pd.read_sql(table_name,engine))
读/写csv文件
import pandas as pd import numpy as np import sqlalchemy from sqlalchemy import create_engine from faker import Factory import random # ''' # read_csv # ''' # # 读取csv # data = pd.read_csv('data1.csv',encoding = 'gbk') # # # 读取文本 # data2 = pd.read_csv('data1.txt',sep = '::',engine='python') # # # 读取Excel # data3 = pd.read_excel('data1.xlsx') ''' 保存文件 ''' fake = Factory().create('ZH_cn') # columns_name = ['name','age','sex','phone_number'] # sex = [random.choice(['男','女']) for k in range(5)] # name = [fake.name_male() if i == '男' else fake.name_female() for i in sex] # age = [random.choice([21,19,22,18,20]) for e in range(5)] # phone_number = [fake.phone_number() for j in range(5)] # # data = np.array([name,age,sex,phone_number]).T # df = pd.DataFrame(data,columns=columns_name) # # # 保存文件为data.csv # # df.index.name = 'name' #与index=True时配合使用 # df.to_csv('data.csv',index = False,header = True) #header:是否把列名存入 #读取 date = ['a','b','c','d'] fb = pd.read_csv('data.csv',header = 0) #header:把第0行做为列名 # fb = pd.read_csv('data.csv',header = None,names=date) fb = fb.set_index('name') print(fb) data2 = pd.read_csv('data1.txt',sep = '::',engine='python') data = pd.read_csv('data1.csv',encoding = 'gbk')
读/写excel文件
pandas提供了 read_excel 函数来读取 "xls" "xlsx" 两种文件。
import pandas as pd import numpy as np import sqlalchemy from sqlalchemy import create_engine from faker import Factory import random fake = Factory().create('ZH_cn') columns_name = ['name','age','sex','phone_number'] sex = [random.choice(['男','女']) for k in range(5)] name = [fake.name_male() if i == '男' else fake.name_female() for i in sex] age = [random.choice([21,19,22,18,20]) for e in range(5)] phone_number = [fake.phone_number() for j in range(5)] data = np.array([name,age,sex,phone_number]).T # df = pd.DataFrame(data,columns=columns_name) # 保存文件为data.xlsx # df.index.name = 'name' #与index=True时配合使用 # df.to_excel('data.xlsx',sheet_name='第一页',index = False,header = True) #header:是否把列名存入 # #读取 date = ['a','b','c','d'] fb = pd.read_excel('data.xlsx',header = 0) #header:把第0行做为列名 # fb = pd.read_excel('data.xlsx',header = None,names=date) # fb = fb.set_index('name') print(fb)
数据过滤获取
通过DataFrame的相关方式可以获取对应的列或者数据形成一个新 的DataFrame, 方便后续进行统计计算。
import pandas as pd import numpy as np import sqlalchemy from sqlalchemy import create_engine from faker import Factory import random fake = Factory().create('ZH_cn') columns_name = ['name','age','sex','phone_number'] sex = [random.choice(['男','女']) for k in range(5)] name = [fake.name_male() if i == '男' else fake.name_female() for i in sex] age = [random.choice([21,19,22,18,20]) for e in range(5)] phone_number = [fake.phone_number() for j in range(5)] data = np.array([name,age,sex,phone_number]).T df = pd.DataFrame(data,columns=columns_name) print(df[['age','sex']]) print(df.loc[:,['age','sex']]) print(df.columns) print(df[df.columns[1:3]])
缺省值NaN处理方法
对于DataFrame/Series中的NaN一般采取的方式为删除对应的列/ 行或者填充一个默认值。

import pandas as pd import numpy as np ''' 缺失值处理 ''' df01 = pd.DataFrame(np.random.randint(1,9,(4,4)),index = list('ABCD'),columns = list('abcd')) df01.loc['B','c'] = np.NaN df01.loc['C','b'] = np.NaN # print(df01) # print(df01['b'].isnull()) ''' dropna ''' # print(df01.dropna()) # 默认会删除带有 NaN 的行 只要包含一个就整行删除 # print(df01.dropna(axis = 1)) # 删除列中带有NaN的列 # 设置阀值 # df01 = df01.dropna(how = 'all') # 只删除整行为 nan的行,默认值为any # print(df01) df01.loc['E'] = np.NaN df01=df01.dropna(how='all') ''' fillna 处理 ''' # print(df01.fillna(0)) # 将所有的 nan 数据替换成了 0 # print(df01.fillna(method = 'ffill')) # 根据前一个值进行替换 # print(df01.fillna(method = 'bfill')) # 根据后一个值进行替换 print(df01.fillna({'b':100,'c':200}) ) # 根据列进行替换 df01.loc['A','a'] = 30 print(df01.replace({np.nan:'null',30:'haha'})) #替换多值 # df01.replace(np.nan,0,inplace=True) #相当于df01 = df01.replace(np.nan,0) print(df01)
常用的数学统计方法


import pandas as pd import numpy as np df01 = pd.DataFrame(np.random.randint(1,9,(4,4)),index = list('ABCD'),columns = list('abcd')) ''' count ''' print(df01.count()) print(df01.count(axis = 1)) ''' min ''' print(df01.min()) print(df01.min(axis = 1)) ''' idmin:返回最小值的下标 ''' print(df01.idxmin()) ''' describe ''' print(df01.describe()) print(df01.mad() ) # 平均绝对距离差
相关系数与协方差
相关系数:就是用X、Y的协方差除以X的标准差和Y的标准差。所以,相关系数也可以看成协方差:一种剔除 了两个变量量纲影响、标准化后的特殊协方差。 1.也可以反映两个变量变化时是同向还是反向,如果同向变化为正,反向变化为负 2.由于它是标准化后的协方差,因此更重的特性是,它消除了两个变量变化幅度的影响,而只是 单纯反应两个变量单位变化的相似程度。 注意: 相关系数不像协方差一样可以在+\infty 到-\infty 间变化,它只能在+1到-1之间变化 当相关系数为1的时候两者相识度最大,同向正相关 当相关系数为0的时候两者没有任何相似度,两个变量无关 当相关系数为-1的时候两者变化的反向相似度最大,完全反向负相关。
import pandas as pd df01 = pd.DataFrame({ 'kill':[5,6,7,8], 'duanwei':[4,2,3,1], 'dgb':[1,3,8,9]}) print(df01['kill'].cov(df01['duanwei'])) print(df01['kill'].corr(df01['duanwei'],method='pearson')) print(df01['kill'].corr(df01['duanwei'],method='kendall')) print(df01['kill'].corr(df01['duanwei'],method='spearman')) print(df01.corr())
唯一值,值计数以及成员资格
unique方法用于获取Series中的唯一值数组(去重数据后的数组)。
Value_counts方法返回一个包含值和该值出现次数的Series对象,次 序按照出现的频率由高到低排序.。
isin方法用于判断矢量化集合的成员资格,可用于选取Series中或者 DataFrame中列中数据的子集。
import pandas as pd df01 = pd.DataFrame({ 'movie_name':list('abadcebe'), 'rating':[4,5,3,5,3,4,3,5] }) print(df01['movie_name'].unique()) result = df01['movie_name'].value_counts().head(3) print(result) print(df01['movie_name'].isin(result.index)) #成员判断 print(df01[df01['movie_name'].isin(result.index)]) #获取成员
层次索引
import pandas as pd import numpy as np ser01 = pd.Series([30,33,35,18,20,30],index = [ [2017,2017,2017,2018,2018,2018], ['messi','cr7','nermaer','messi','cr7','nermaer'] ]) # print(ser01) # 获取数据 # print(ser01[2017,'messi']) # print(ser01[2018]['cr7']) # print(ser01[2018][['messi','cr7']]) # print(ser01[:,'nermaer']) # print(ser01.swaplevel()) #交换索引级别 # print(ser01.swaplevel().sort_index()) #排序索引 # print(ser01.swapaxes()) # 转换成dataFrame # ser01=ser01.unstack(level = 1) #把行索引分解成列索引 # print(ser01) # print(ser01.stack()) ##把列索引合并成行索引 # # print(ser01.stack().index) #MultiIndex(levels=[[2017, 2018], ['cr7', 'messi', 'nermaer']],codes=[[0, 0, 0, 1, 1, 1], [0, 1, 2, 0, 1, 2]]) codes为levels的下标。 ''' dataframe ''' df01 = pd.DataFrame({ 'year':[2017,2017,2017,2018,2018,2018], 'goal':[30,30,31,28,29,30], 'zg':[15,16,13,18,13,14], 'name':['messi','cr7','nermaer','messi','cr7','nermaer'] }) '''列 ——> 索引''' # df01 = df01.set_index(['year','name']) df01.set_index(['year','name'],inplace=True) '''索引 ——> 列''' #方法一 # print(np.array(list(df01.index))) # year,name = zip(*list(df01.index)) #拆解多层索引 # df01['year'] = year #方法二 # print(df01.reset_index(level=['year','name'])) # df01.reset_index(level=0, inplace=True) #方法三 # print(df01.index.get_level_values('year')) # df01['year'] = df01.index.get_level_values('year') '''按层次索引进行统计''' print(df01.sum(level='year')) print(df01.mean(level='year')) print(df01.sum(level='name')) print(df01.mean(level='name')) print(df01)
Pandas排序之sort_index与sort_values
sort_index 对行或列索引进行排序。
Series 的 sort_index(ascending=True) 方法可以对 index 进行排序 操作,ascending 参数用于控制升序或降序,默认为升序。
在 DataFrame 上,.sort_index(axis=0, ascending=True) 方法多了 一个轴向的选择参数。
sort_values对Series按值进行排序, 排序时,任何缺失值默认都会被放到Series的 末尾。
import pandas as pd import numpy as np ''' sort_index ''' ser01 = pd.Series([1,2,3,4,5],index = list('bdcae')) # print(ser01) # print(ser01.sort_index(ascending = True)) # 通过索引进行排序 df01 = pd.DataFrame(np.random.randint(1,9,(4,4)),index = list('BCDA'),columns = list('cadb')) # print(df01) # # print(df01.sort_index(axis = 0)) # 默认对行索引进行排序 # print(df01.sort_index(axis = 1)) ''' sort_values ''' ser02 = pd.Series([4,5,2,7,1],index = list('bdcae')) print(ser02.sort_values(ascending = False)) # 倒序 df02 = pd.DataFrame(np.random.randint(1,9,(4,4)),index = list('BCDA'),columns = list('cadb')) print(df01.sort_values(by = ['a','c'],ascending = False)) print(df01.sort_values(by = 'B',axis=1,ascending = False))
Pandas排名之rank
import pandas as pd import numpy as np ''' rank ''' # ser01 = pd.Series([4,5,2,2,1,2],index = list('bdcaef')) # print(ser01.rank()) # 有重复的数字的排名则按它们的排名取均值:(2 + 3 + 4)/3 = 3 # print(ser01.rank(method = 'min')) #默认 average # print(ser01.rank(method = 'max')) # print(ser01.rank(method = 'first')) df = pd.DataFrame(np.random.randint(0,5,(4,4))) print(df) print(df.rank(method='min',ascending=False)) #按照列排名 print(df.rank(axis=1)) #按照行排名
Pandas之时间序列
在pandas中有一个非常常用的函数date_range,尤其是在处理时间 序列数据时,这个函数的作用就是产生一个DatetimeIndex,就是时 间序列数据的索引。
pandas.date_range(start=None, end=None, periods=None, freq=’D’, tz=None, normalize=False, name=None, closed=None, **kwargs)
参数:
start:string或datetime-like,默认值是None,表示日期的起点。
end:string或datetime-like,默认值是None,表示日期的终点。
periods:integer或None,默认值是None,表示你要从这个函数产生多少个日期索引值;如果是None的话,那么start和end 必须不能为None。
freq:string或DateOffset,默认值是’D’,表示以自然日为单位,这个参数用来指定计时单位,比如’5H’表示每隔5个 小时计算一次。
tz:string或None,表示时区,例如:’Asia/Hong_Kong’。
normalize:bool,默认值为False,如果为True的话,那么在产生时间索引值之前会先把start和end都转化为当日的午夜0点。
name:str,默认值为None,给返回的时间索引指定一个名字。
closed:string或者None,默认值为None,表示start和end这个区间端点是否包含在区间内,可以有三个值,’left’表示 左闭右开区间,’right’表示左开右闭区间,None表示两边都是闭区间。
import pandas as pd import numpy as np # pd.date_range(start = '20180701',end = '20180708') # print(pd.date_range(start = '20180701',end = '20180708',freq = '2d')) # print(pd.date_range(start = '20180701',periods = 5,freq = 'm')) # print(pd.date_range(start = '20180701',end = '20180708',freq = '12h')) # print(pd.date_range(start = '20180701',periods = 10,freq = '10min')) print(pd.date_range(start = '20180701',periods = 10,freq = '10s'))
Pandas之表合并
merge:
pandas.merge 可根据一个或多个键将不同 DataFrame 中的行连接起来。 on=None 用于显示指定列名(键名),如果该列在两个对象上的列名不同,则可以通过 left_on=None, right_on=None 来分别指定。或者想直接使用行索引作为连接键的话,就将 left_index=False, right_index=False 设为 True。
how='inner' 参数指的是当左右两个对象中存在不重合的键时,取结果的方式:inner 代表交集;outer 代表并集;left 和 right 分别为取一边。
suffixes=('_x','_y') 指的是当左右对象中存在除连接键外的同名列时,结果集中的区分方式,可以各加一个小尾巴。
对于多对多连接,结果采用的是行的笛卡尔积。
concat:
pandas.concat 可以沿着一条轴将多个对象堆叠到一起 objs: series,dataframe或者是panel构成的序列lsit axis: 需要合并链接的轴,0是行,1是列。
join:连接的方式 inner,或者outer
import pandas as pd import numpy as np df01 = pd.DataFrame({ 'data1':[1,2,3,4,5], 'key':list('abcde') }) df02 = pd.DataFrame({ 'data2':[1,2,3,4,6], 'key':list('abcdf') }) # print(df01) # print(df02) ''' merge ''' print(pd.merge(df01,df02,on = 'key',how = 'inner')) #取'key'的交集 print(pd.merge(df01,df02,on = 'key',how = 'outer')) #取'并集'的交集 print(pd.merge(df01,df02,on = 'key',how = 'left')) print(pd.merge(df01,df02,on = 'key',how = 'right')) print(pd.merge(df01,df02,left_on = 'data1',right_on = 'data2',how = 'inner')) print(pd.merge(df01,df02,left_on = 'data1',right_on = 'data2',how = 'outer',suffixes=('_1','_2'))) print(pd.merge(df01,df02,left_on = 'data1',right_on = 'data2',how = 'left')) print(pd.merge(df01,df02,left_on = 'data1',right_on = 'data2',how = 'right')) ''' concat ''' print(pd.concat([df01,df02],join = 'outer',sort=False) ) # 纵向合并 print(pd.concat([df01,df02],axis=1,join = 'outer',sort=False) ) # 纵向合并
Pandas分组与聚合操作
groupby 对DataFrame进行数据分组,传入列名列表或者Series序 列对象,返回生成一个GroupBy对象。它实际上还没有进行任何计算。
GroupBy对象是一个迭代对象,每次迭代结果是一个元组。
元组的第一个元素是该组的名称(就是groupby的列的元素名称)。 第二个元素是该组的具体信息,是一个数据框。
索引是以前的数据框的总索引。
import pandas as pd import numpy as np df01 = pd.DataFrame({ 'data1': [1, 2, 3, 4, 5], 'data2': [10, 20, 30, 40, 50], 'key1': list('aabba'), 'sex': list('mwwmm') }) print(df01) #通过一列数据分组获取一列数据或两列数据 print(df01.groupby('key1')) for i in df01.groupby('key1'): print(i[1]) print(df01.groupby('key1')['data1'].sum()) print(df01.groupby('key1')['data1'].mean()) print(df01.groupby('key1')['data1','data2'].max()) #通过两列数据分组获取一列数据或两列数据 for i in df01.groupby(['key1','sex']): print(i) print(df01.groupby(['key1','sex'])['data1'].max()) print(df01.groupby(['key1','sex'])['data1'].max().unstack()) print(df01.groupby(['key1','sex'])['data1','data2'].max())
Pandas聚合之apply
apply 是 pandas 库的一个很重要的函数,多和 groupby 函数一起 用,也可以直接用于 DataFrame 和 Series 对象。主要用于数据聚合 运算,可以很方便的对分组进行现有的运算和自定义的运算。

import pandas as pd import numpy as np df01 = pd.DataFrame({ 'data1': [1, 2, 3, 4, 5], 'data2': [10, 20, 30, 40, 50], 'key1': list('aabba'), 'sex': list('mwwmm') }) print(df01) ''' apply ''' # print(df01.groupby(['sex'])['data1'].apply(lambda x : x+10)) #做四则运算时则合并分组 # print(df01.groupby(['sex'])['data1'].apply(lambda x : x*10)) #做四则运算时则合并分组 # print(df01.groupby(['sex'])['data1'].apply(lambda x : x.sum())) #做统计是则分组运算 # print(df01.groupby(['sex'])['data1'].apply(lambda x : x.mean())) #做统计是则分组运算 np.random.seed(28) df01 = pd.DataFrame(np.random.randint(1,9,(4,4)),index = list('ABCD'),columns = list('abcd')) print(df01) def f1(x): return x*10 print(df01.apply(f1)) def f2(x): if x['B'] == 5: x['B'] = 200 print(x) return x print(df01.apply(f2,axis=0)) #按列遍历,axis=1,则按行遍历 print(df01) # 传递参数 def f3(x,y): if x['a'] == 200: x['a'] = str(x['a'])+ y return x print(df01.apply(f3,args = ('hahha',),axis = 1)) ''' 练习一: 要求:提取数据时间部分,返回对应的每行数据的年、月、日三列数据。效果如右下图所示。 ''' df02 = pd.DataFrame(np.random.randint(1,9,(4,4)),columns = list('ABCD')) df02['E'] = pd.date_range(start = '20180702',periods = 4,freq = 'd') print(df02) import time def get_time(x): # 转换时间元组 tup_time = time.strptime(str(x),'%Y-%m-%d %H:%M:%S') return pd.Series([tup_time[0],tup_time.tm_mon,tup_time.tm_mday],index = list('YMD')) # 使用Series返回 生成DataFrame print(df02['E'].apply(get_time)) ''' 练习二 ''' df6 = pd.DataFrame({ 'name': ['joe', 'susan', 'anne', 'black', 'monika', 'ronaldo', 'leonarldo', 'tom', 'yilianna', 'bulanni'], 'age': [19, 19, 18, 20, 20, 18, 19, 20, 18, 19], 'sex': ['man', 'women', 'women', 'man', 'women', 'man', 'man', 'man', 'women', 'women'], 'address': ['上海', '北京', '上海', '北京', '北京', '上海', '北京', '上海', '北京', '上海'], 'money': [8000, 8500, 7000, 9000, 10000, 7500, 8800, 9300, 12000, 11000] }) print(df6) # 根据地区进行分组 查看平均年龄和工资 def f1(x): # print(x) return x.mean() # print(df6.groupby('address')['age','money'].apply(f1)) # 根据年龄进行分组 查看平均工资 print(df6.groupby('age')['money'].apply(f1)) # 根据性别进行分组 查看平均工资 df6.groupby('sex')['money'].apply(f1) # 先根据地区,然后在根据性别进行分组,查看各地区不同性别的平均工资 df6.groupby(['address','sex'])['money'].apply(f1) '''agg:分组函数 可以同时应用多个聚合函数''' #根据地区进行分组 查看工资的平均值 #最低值 最高值 和最高值与最低值的差 #agg()分组函数 可以同时应用多个聚合函数 def y(x): return x.max() - x.min() print(df6.groupby(['address'])['money'].agg(['mean','max','min',('cha',y)])) ''' 练习三 根据性别进行成绩排序 计算男女比例 计算成绩分布,每个成绩段有多少人 ''' df = pd.DataFrame({'性别' : ['男', '女', '男', '女', '男', '女', '男', '男'], '成绩' : ['优秀', '优秀', '及格', '差', '及格', '及格', '优秀', '差'], '年龄' : [13,14,15,12,13,14,15,16]}) # 替换成绩字段 df = df.replace({'优秀':'A','及格':'B','差':'C'}) # print(df) #根据性别进行成绩排序 def sotrs(x): print(x) return x.sort_values(by = '成绩') print(df.groupby('性别').apply(sotrs)) # 计算男女比例 total = df['性别'].count() # 获取总人数 sexs = df.groupby('性别')['性别'].count() print(sexs) print(sexs.apply(lambda x : str(x/total*100)+'%')) # 计算成绩分布,每个成绩段有多少人 total = df['性别'].count() # 获取总人数 score = df.groupby('成绩')['成绩'].count() score.apply(lambda x : str(x/total*100)+'%')
Pandas之数据透视
数据透视表pivot_table,根据一个或多个键进行聚合,并根据行列上的 分组键将数据分配到各个矩形区域中。 DataFrame.pivot_table(data, values=None, index=None, columns=None, aggfunc=’mean’, fill_value=None, margins=False, dropna=True, margins_name=’All’)。
data: DataFrame对象。
values: 显示的列的名字,可以应用aggfunc中的函数。
index: 索引。
columns: 可选的, 通过额外的方法来分割你所关心的实际值,然而aggfunc被应用到values上, aggfunc默认的是mean。
import pandas as pd import numpy as np df = pd.DataFrame({ 'kill':[1,2,3,4,5], 'address':['皮卡多','圣马丁','皮卡多','圣马丁','皮卡多'], 'help':[3,4,2,5,2], 'sex':['m','w','m','m','w'] }) # 通过index 进行 分组 查看 values 中的字段 的 aggfunc 值 print(df.pivot_table(values = ['kill','help'],index = ['address'],aggfunc = np.mean)) print(df.groupby('address')['kill','help'].apply(lambda x:x.mean())) print(df.groupby('address')['kill','help'].mean()) print(df.pivot_table(values = ['kill','help'],index = ['address'],aggfunc = [np.mean,np.max,np.min])) print(df.pivot_table(values = ['kill','help'],index = ['address'],columns = ['sex'],aggfunc = np.mean))
Pandas之去重
import pandas as pd import numpy as np arr = np.array(['b','a','a','a','d','a','b','c','b','b','a','a','b','b','f','e']).reshape(8,2) df = pd.DataFrame(arr,columns=['a','b']) print(pd.unique(df['a'])) print(df.drop_duplicates(subset='a')) #在 'a' 列上有重复的删除行 print(df.drop_duplicates(subset='a',keep='last')) #可以选定保留哪一行。 print(df.drop_duplicates(subset=['a','b'])) #在 'a' 列 和 'b' 列上每一行组成一个子集,若子集出现重复则删除行
pandas制图
import matplotlib.pyplot as plt import matplotlib as mpl import numpy as np import pandas as pd # 设置中文显示 mpl.rcParams['font.sans-serif'] = ['SimHei'] mpl.rcParams['axes.unicode_minus'] = False ser = pd.Series(np.random.randn(10).cumsum(),index = np.arange(0,100,10)) ser1 = pd.Series(np.random.randn(10).cumsum(),index = np.arange(0,100,10)) ser.plot() ser1.plot(color = 'r') plt.show() # DataFrame # df = pd.DataFrame(np.random.randint(1,9,(4,2)),index = ['1月','2月','3月','4月'],columns = ['鼓浪屿','张家界']) # df.plot(kind = 'bar') # plt.show()
pandas之加载网上数据
官网:https://pandas-datareader.readthedocs.io/en/latest/remote_data.html
准备工作:
pip install pandas==0.24.0
pip install pandas-datareader==0.6.0
pip install yfinance==0.1.43
把原fred.py文件到开头import中第一句是这个 from pandas.core.common import is_list_like 我们将这个句修改成:from pandas.api.types import is_list_like。
#定义所需要的数据 gafataDict={"谷歌":"GOOG","亚马逊":"AMZN","Facebook":"FB","苹果":"AAPL","阿里巴巴":"BABA","腾讯":"0700.hk"}
import pandas as pd import numpy as np from pandas_datareader import data, wb # 需要安装 pip install pandas_datareader import datetime import matplotlib.pyplot as plt import matplotlib import yfinance as yf matplotlib.style.use('ggplot') %matplotlib inline %pylab inline %config InlineBackend.figure_format = 'retina' yf.pdr_override() # 用来修复,必要 # 定义获取数据的时间段 start = datetime.datetime(2019, 1, 1) end = datetime.date.today() # 获取股票信息 ex: 中国石油 # 如果要看上证指数请参考换成600000.ss # 如果要看深成指请换成000001.sz cnpc = data.get_data_yahoo("601857.SS", start, end) '''数据读取和输出pd.read_csv and to_csv''' # cnpc.to_excel('cnpc_datas.xls',index = False,header = True) # df = pd.read_excel('cnpc_datas.xls',header=0) '''清洗数据''' # 把所有数据都为0的列删除。 print(cnpc.shape) print(cnpc.info()) abnormal_value = np.array([0 for i in range(cnpc.shape[0])]) for i in cnpc.columns: # print((~(cnpc[i]==abnormal_value)).astype(np.int).mean()) if np.mean((cnpc[i]==abnormal_value).astype(np.int)) > 0.5: cnpc.drop(i,axis=1) '''检查缺失值''' # 下面把一些位置设置为np.nan,然后填充,没有实际意义,这里只是拿来练手。 cnpc.iloc[0,:] = np.nan cnpc.iloc[[1,3],1] = np.nan cnpc.iloc[2,2] = np.nan cnpc.iloc[3,3] = np.nan print(cnpc.info()) pd.isnull(cnpc).head() # or cnpc.isnull() print(cnpc.isnull().values.any(axis=0)) # 统计nan值 print(cnpc.isnull().values.any(axis=1)) print(cnpc.isnull().values.all(axis=1)) print(cnpc.isnull().values.sum(axis=0)) # 每列有多少个nan值 print(cnpc.isnull().values.sum(axis=1))# 每行有多少个nan值 print(cnpc.isnull().values.sum()) # 总共有多少个nan值 '''填补缺失值''' cnpc.dropna(how='all',inplace=True) # print(cnpc.head()) # cnpc.replace(np.nan,0,inplace=True) cnpc['High'].fillna(cnpc['High'].mean(),inplace=True) #fill in with mean # cnpc['Low'].fillna(method='ffill',inplace=True) #fill in with value from previous row # cnpc['Close'].fillna(method='bfill',inplace=True) # fill in with value from the row behind print(cnpc) '''计算涨跌额''' # 涨跌额是指当日股票价格与前一日收盘价格相比的涨跌数值。 # 添加一列change,其为当日close价格与之前一天的差值。当然注意这里数据有缺失,有的日期没有记录。 # print(cnpc.Close-cnpc.Close.shift()) change = cnpc.Close.diff() change.fillna(change.mean(),inplace=True) #插入列 # cnpc.insert(6,'change', change) cnpc['Change'] = change # print(cnpc) # 按涨跌额排序,未改变sh,若需要,可以`inplace=True` print(cnpc.sort_values(by='Change',ascending=False).head(3)) # 用shift方法错位 # cnpc['pct_change'] = ((cnpc['Change'].shift(-1)-cnpc['Change']) / cnpc['Change']) # 或用pct_Change函数 cnpc['pct_change'] = cnpc.Change.pct_change() cnpc.iloc[5:9] format = lambda x: '%.2f' % x # cnpc = cnpc.applymap(format) cnpc = cnpc.applymap(float) # 可以重新把数据类型转换为float类型 def f(x): return pd.Series([x.min(),x.max(),x.max()-x.min()],index=['min','max','range']) # cnpc.apply(f) # 按月分组 cnpc['group_index'] = cnpc.index.map(lambda x: 100*x.year + x.month) # 对不同的列运用不同的函数聚合 def peak_to_peak(arr): return arr.max() - arr.min() grouped = cnpc.groupby('group_index').agg({ 'Open' : peak_to_peak, 'High' : 'max', 'Low' : 'min', 'Change' : 'mean' }) # grouped_1 = cnpc.groupby(pd.TimeGrouper("M")).agg({ # 'Open' : peak_to_peak, # 'High' : 'max', # 'Low' : 'min', # 'Change' : 'mean' # }) cnpc.describe() # 数据整体概览 '''可以把相似度高的维度删掉‘’‘ part=cnpc[['Open', 'High', 'Low', 'Close','Volume']] cov = np.corrcoef(part.T) # 通过矩阵的转置 print(cov) img = plt.matshow(cov,cmap=plt.cm.winter) plt.colorbar(img, ticks=[-1,0,1]) plt.show()
pandas的输出问题
关于Python数据分析中pandas模块在输出的时候,每行的中间会有省略号出现,和行与行中间的省略号....问题,其他的站点(百度)中的大部分都是瞎写,根本就是复制黏贴以前的版本,你要想知道其他问题答案就得去读官方文档吧:https://pandas.pydata.org/pandas-docs/stable/user_guide/options.html。
如果数据行很多的话,对于pandas模块是自动默认只显示100行数据,如果超100行,例如120行,则中间的20行会被“ ... ”替代!
先处理pandas 读取数据后在行中间省略部分的处理:
#显示被省略的列 pd.set_option('display.width',None) #最大显示所有行 pd.set_option('display.max_rows',None)

浙公网安备 33010602011771号