Pandas

来源:互联网 发布:网络意识形态实施方案 编辑:程序博客网 时间:2024/05/16 13:52

Pandas(panel data & Data Analysis):最流行的Python数据分析库


import pandas as pd


基于Numpy,专用于数据预处理和数据分析的Python第三方库,最适合处理大型结构化表格数据

  • Series 一维,带标签数组
  • DataFrame 二维,Series容器,最常用
  • Panel 三维,DataFrame容器

list:Python自带数据类型,功能简单,操作复杂,效率低
ndarray:基础数据类型,关注数据结构/运算/维度(数据间关系)
Series/DataFrame:扩展数据类型,关注数据与索引的关系,数据实际应用

从实用性、功能强弱和和可操作性比较:list < ndarray < Series/DataFrame
实践工作中,ndarry数组作为必要补充,大部分数据尽量使用Pandas数据类型


// 数据类型

# Series 一维pd.Series([2,4], index=['周', '孔'])pd.Series(    {    'hong':50,     'huang':90,    })# 取值.loc('索引', 列)# 取索引的值.index()# 取值# 查询多值a[[1,3,4]]# 位置切片,默认索引,左闭右开b[:3]# 标签切片,自定义索引# 注意:两边都闭区间(因为使用标签索引时通常不知道标签顺序,很难确定结束前一个标签是什么)b[:'huang'] b['huang':]# 步长b[::2] b[::-1] #步长-1,逆序# 过滤b >= 60b[b >= 60]# 标量算数运算b + 1# 应用函数np.median(b) # 中位数b.median() # 方法调用写法'c' in b # 判断此键在不在b的索引中# 0 in b # 错误,in不会判断自动索引b.get('zi',60) #从b中提取索引zi的值,如果存在就取出,不存在用60代替# values值修改b['ming'] = 0b['hua','hong'] = 55 # b[['hua','hong']] = 20b['hua','hong'] = [35,55]b# 索引修改b2 = b.copy() # 复制副本而非引用视图,类似深拷贝b2.index = ['xiaoming','xiaohua','xiaohong','xiaohuang','xiaobai']# Series对象和索引命名s.indexs.name

// 数据类型-DataFrame
DataFrame对象是Pandas最常用的数据类型

  • 表格型数据结构,类似EXCEL或关系型数据库中的二维表,实际应用非常广泛
  • DataFrame对象是由多个Series对象作为列组成的表格数据类型,每行Series值都增加了一个共用的索引
  • 是Series对象的容器,可视为:二维的带标签数组,或由Series组成的字典

DataFrame对象既有行索引,又有列索引

  • 行索引,表明不同行,横向索引,叫index,0轴,axis=0
  • 列索引,表名不同列,纵向索引,叫columns,1轴,axis=1

其他情况:

  • 基本操作类似Series,依据行列索引操作
  • 内存中以一个或多个二维块存放,而不是列表、字典或别的一维数据结构
  • 常用于表达二维数据,但也可以表达多维数据(层次化索引的表格型结构)

(等长)列表或Numpy数组组成的字典 创建DataFrame,注意必须等长否则报错

# 二维数组, 索引和列名pd.DataFrame([[2,4,6,8,10], [12,14,16,18,20]], index=['语文', '数学', '英语'], columns=['周', '孔', '王', '李'])pd.DataFrame(    ['小明','male',18,170,60,'北京海淀',61],    ['小华','female',28,160,50,'上海静安',90],    index=[1,2],                                                    # 行索引    columns=['name','sex','age','heigh','weight','address','grade'] # 列索引)# 指定列排序d = pd.DataFrame(cv,columns=['name','sex','age'])# 传入列在数据中找不到,会产生NA值e = pd.DataFrame(cv,index=[1,2,3,4,5],columns=['name','sex','age','heigh'])------------------------------------------------------------------------------# 嵌套字典(字典组成的字典) 创建DataFrame,不等长也可,自动填充NaN# 外层键是列索引,内层键是行索引fv = {    'name':{1:'小明',2:'小华',3:'小红',4:'小青',5:'小兰'},    'sex':{1:1,2:0,3:0,4:1,5:0},    'age':{2:28,3:38,4:48,5:8} # 少一个值自动填充为Nan}f = pd.DataFrame(fv)# 指定内层字典键(行索引),没有的值会填充NaNg = pd.DataFrame(fv,index=[3,4,2,6])---------------------------------------------------------------------------------# Series组成的字典 创建DataFrame,同嵌套字典# 外层键是列索引,内层键是行索引hv = {    'name':pd.Series(['小明','小华','小红','小靑','小兰'],index=[1,2,3,4,5]),    'sex':pd.Series([1,0,0,1,0],index=[1,2,3,4,5]),    'age':pd.Series([28,38,48,8],index=[2,3,4,5]) # 少一个值自动填充为NaN}h = pd.DataFrame(hv)# 指定内层字典键(行索引),没有的值会填充NaNi = pd.DataFrame(hv,index=[3,4,2,6])# Series对象和索引命名ss.name #默认没有s.name = 'uname' # Series对象命名ss.names.indexs.index.name = 'cname' # 索引命名ss.index-------------------------------------------------------------------------------# ndarray数组 创建DataFrame# 自动生成行列索引j = pd.DataFrame(np.arange(10).reshape(2,5)) # 自定义行列索引k = pd.DataFrame(    np.random.randn(6,4),    index=[1,2,3,4,5,6],    columns=['a','b','c','d'])# axis=1删除列,默认axis=0删除行b.drop(['math','chinese'],axis=1)# 遍历DataFramefor index, row in a.iterrows():#     print(index) # 行索引#     print(row) # 值,按行排列    print(row[0]) # 单元格# 查看维度a.shape# 查看类型a.dtypes# 查看值a.values# 查询单值a['name'][2]        # 必须先列后行# 查看结构什么样的a.head(3)            # 显示头部几行,默认5行a.tail(3)            # 显示末尾几行,默认5行a.info()             # 相关信息概览:行数,列数,列索引,列非空值个数,列类型,列类型,内存占用a.describe()         # 快速综合统计结果:计数,均值,标准差,最大值,四分位数,最小值
# 索引查询# 用于连续或不连续(行列有间隔)行列区块查询# 解决了DataFrame进行行标签查询的问题# 两种查询方式:    #a.loc[行,列],标签索引,自定义索引    #a.iloc[行,列],位置索引,默认索引# 参数书写顺序都是都是先行后列# 查询单行a.loc[1] # 标签索引a.iloc[1] # 位置索引,从0开始# 查询单列a.loc[:,'name'] # 标签索引a.iloc[:,0] # 位置索引# 查询多行,双中括号a.loc[[2,4]] # 标签索引a.iloc[[1,3]] # 位置索引# 查询多列a.loc[:,['name','address']] # 标签索引a.iloc[:,[0,5]] # 位置索引# 查询单个单元格a.loc[1,'name'] # 标签索引,先行后列,一行一列a.at[1,'name'] # 同上,但速度更快效率更高a.iloc[0,0] # 位置索引a.iat[0,0] # 同上,但速度更快效率更高# 查询多个单元格a.loc[1,['name','address']] # 一行多列,Seriesa.loc[[1,3],'address'] # 多行一列,Seriesa.loc[[1,3],['name','address']] # 多行多列,不连续,DataFramea.iloc[0,[0,5]]a.iloc[[0,2],5]a.iloc[[0,2],[0,5]]
# 切片查询# 用于连续行列区块查询# 比索引查询简单方便,但不能查询非连续行列区块# 单个或不连续行列区块使用索引查询,连续行列区块使用切片查询# 切片查询的区间:# iloc 默认位置索引是左闭右开区间(包含起始元素,不包含结束元素)# loc 自定义标签索引是左闭右闭区间(包含起始元素,也包含结束元素)# 因为标签索引不包含位置信息,使用时很难知道索引前后是什么# 选取一行a.loc[2,:] # 等价于 a.loc[2]a.iloc[1,:] # 等价于 a.iloc[1]# 选取一列a.loc[:,'sex']a.iloc[:,1]# 切片选取连续多行a.loc[:3,:] # 左闭右闭a.iloc[:3,:] # 左闭右开# 切片选取连续多列a.loc[:,'heigh':'address']a.iloc[:,3:6]# 切片选取多行多列的聚合a.loc[3:5,'sex':'heigh'] a.iloc[2:5,1:4]
# 过滤查询# 通过列布尔值过滤、筛选查询# 不通过索引而是通过值查询# 用于结果索引不确定的查询# 通过运算所得布尔值对查询结果进行过滤# 通过某列值过滤数据,返回布尔值a['grade'] >= 60a.loc[:,'grade'] >= 60# 布尔值做DataFrame参数,返回Dataframe对象a[a['grade'] >= 60]a[a.loc[:,'grade'] >= 60]# 布尔索引和切片结合a.loc[a['grade'] > 60,'address':] # 行,列# 多重条件过滤,逻辑运算# & 且# | 或# - 非(或用 != 判断)(a['grade'] >= 60) & (a['sex'] == 'female')a[(a['grade'] >= 60) & (a['sex'] == 'female')]# 通过where过滤选取数据a > 60a < 30a[a > 60]a[a < 30]# where过滤dColumns = a[['name','weight','grade']] # 获取3列数据dBool = dColumns > 60 # 判断布尔值dNan = dColumns[dBool] # 过滤查询dNandNan.dropna(how='any') # 丢掉含有缺失值的行# 通过isin()过滤选取数据# 查询某列中包含某值的所有行a['address'].isin(['北京海淀','深圳南山'])a[a['address'].isin(['北京海淀','深圳南山'])]
# 修改,Update# 凡能通过查询得到的值,直接赋值就可修改# 视图和副本: 通过索引和切片返回的数据是原数据的视图,不是副本,任何对视图的修改全部会反映到源数据上,想独立修改数据可以通过copy()复制源数据的副本# 类list/ndarray查询方式修改b = a.copy()bb['heigh']b['heigh'] = 170b['heigh'] = [150,160,170,180,190]b# 索引或切片查询方式修改b.loc[[1,3,5],['age','heigh']]b.loc[[1,3,5],['age','heigh']] = [[10,100],[20,200],[30,300]] # 3行2列# b.loc[[1,3,5],['age','heigh']] = [[1,2,3],[4,5]] # 错误,维度不匹配b# 通过where过滤修改b[b > 60]b[b > 60] = 1 # 错误,不能在混合数据类型中修改非NaN值# 提取唯一数据类型数据c = a.loc[:,['weight','grade']].copy()c2 = c.copy()cc > 60c[c > 60]c[c > 60] = 1 # 修改非NaN值c-(c2 > 60) # 非,或 c2 <= 60c2[-(c2 > 60)] = 1c2
# 删除,Delete# Series对象删除值s.drop('ming')# DataFrame对象删除值# 默认删除行,默认只改动视图b.drop(1) # 删除单行b.drop([1,7]) # 删除多行# 删除列# axis=1删除列,默认axis=0删除行b.drop('math',axis=1)b.drop(['math','chinese'],axis=1)# inplace=True 改动原数据,默认inplace=False 只改动视图b.drop(['math','chinese'],axis=1,inplace=True)# DataFrame对象的索引命名b.index.name = 'hang'b.columns.name = 'lie'

这里写图片描述


// Pandas数据存取
Pandas可以存取多种介质类型数据,例如:内存、文本、CSV、JSON、HTML、Excel、HDF5、SQL等

# 写入CSV# 数据有中文,编码可以修改,默认ascii,改为utf-8# 写入不修改编码则读取时需要修改df.to_csv(    'foo2.csv', # 存入数据    index=False, # 不存储行索引    header=False, # 不存储列索引    encoding='utf-8' # 修改编码)# 读取CSV# csv文件内有汉字等特殊符号时,csv文件编码应为utf-8(无BOM)可默认正常读取,如果编码是ANSI,加参数encoding='gbk'# 数据内有逗号时,左右加英文半角双引号,可以正常解析pd.read_csv(    'foo2.csv', # 文件名    sep=',', # 指定分隔符,csv默认逗号,如果是table表格数据一般为 \t    usecols=[0,1,2,4], # 读取指定列    nrows=10, # 读取前几行    header=None, # 不将第一行设为表头    names=['a','b','c','d'], # 不使用csv表头,自定义表头    encoding='utf-8' # 编码,需要根据文本编码修改,默认utf-8,可以指定为GBK/ascii)# 合并时间列及自定义某列为行索引'''data,time,name,age20100101,000000,"张三",1820100101,230000,"李,四",28'''pd.read_csv(    'foo.csv',    parse_dates={'shijian': ['data','time']}, #将两列合并解析为时间格式    index_col='shijian', #将某列设为行索引)
# Pandas存取HDF5# 有中文,存储变的异常的大# 写入HDF5df.to_hdf('foo.h5','df')# 从HDF5读取pd.read_hdf('foo.h5','df')一个h5文件可写入多个变量a.to_hdf('foo.h5','abc')pd.read_hdf('foo.h5','abc')
# Pandas存取Excel(xlsx)# 写入Excel文件df.to_excel(    'foo.xlsx', # 写入数据    'Sheet1', # 工作表标签    header=False, # 不存入列索引    index=False # 不存入行索引)# 从Excel文件读取# 分别读取pd.read_excel('output.xlsx', 'Sheet1', index_col=None, na_values=['NA'],header=None) # 不将第一行设为表头pd.read_excel('output.xlsx', 'Sheet2', index_col=None, na_values=['NA'])
# Pandas存取JSON# 存入JSONa.to_json('foo.json')# 读取JSONpd.read_json('foo.json')
# Pandas从剪贴板(内存)读取数据# 多用于将网页内容转换为DataFramepd.read_clipboard()# 不将第一行设为表头pd.read_clipboard(header=None) 

// Pandas存取数据库

这里写图片描述

from sqlalchemy import create_engine# 连接MySQL数据库,需要安装Python连接库# conda install -c anaconda pymysql dbconnect = 'pymysql'            # MySQL连接库,根据使用的连接库修改名称,这里用pymysqldbname = 'aaa'                   # 数据库名dbusername = 'root'              # 数据库用户名dbpwd = 'root'                   # 数据库密码# 连接数据库conn = create_engine('mysql+' + dbconnect + '://' + dbusername + ':' + dbpwd + '@localhost:3306/' + dbname + '?charset=utf8')
# 存取数据库数据# 查询数据库sql1 = 'SELECT * FROM ccc'df1 = pd.read_sql( # pd.io.sql.read_sql()的快捷方式    sql1, # sql语句    conn, # 数据库连接    index_col='id' # 选定某列做行索引,可选)df1# 插入数据库apd.io.sql.to_sql(    a, # 插入的数据,注意格结构应和MySQL表一致    'ccc', # 表名    con=conn, # 数据库连接    if_exists='append', # 注释见下    index=False # 不将列索引插入数据库中,否则会出错)

这里写图片描述


// Pandas统计分析

pandas数据的基本统计分析和numpy的函数近似

dates = pd.date_range('20130101',periods=10)datesdf = pd.DataFrame(np.random.randn(10,4),index=dates,columns=['A','B','C','D'])dfdf.describe() #快速统计结果df.mean() # 按列求平均值df.mean(1) # 按行求平均值

这里写图片描述

a.argmin()b.idxmin()a = pd.Series([9,8,7,6],index=['a','b','c','d'])ab = pd.DataFrame(np.arange(20).reshape(4,5),index=['c','a','d','b'])ba.describe()type(a.describe()) #series对象a.describe()['count']b.describe() #默认0轴运算type(b.describe()) #dataframe对象#返回横行数据,seriesb.describe().loc['max']b.describe().iloc[7]#返回一列值,这里第2列b.describe()[2]#b.describe()[2]b.describe().loc[:,2]

数据的累计统计分析

  • 对序列的前1-n个数累计运算
  • 可减少for循环的使用

可用于金融数据分析中的计算累计盈亏
这里写图片描述

滚动计算(窗口计算)函数

可用于金融数据分析中的计算每笔盈亏
这里写图片描述

原创粉丝点击