zoukankan      html  css  js  c++  java
  • Python之科学运算Pandas模块

    一、Series数列

    Series
    Series是一种类似与一维数组的对象,由下面两个部分组成:
    values:一组数据(ndarray类型)
    index:相关的数据索引标签

    Series的创建
    第一种:由列表或numpy数组创建
    列表创建:
    Series([1,2,3,4,5],index=['a','b','c','d','e'],name='Hello')
    ndarray创建
    a1 = np.array([1,2,3,4,5])
    Series(a1,index=["a","b","c","d","e"],name='hello')
    第二种:由字典创建:不能在使用index.但是依然存在默认索引
    注意:数据源必须为一维数据
    dict = {'hello':12,'hey':30}
    Series(data=dict)

    Series的索引
    可以使用中括号取单个索引(此时返回的是指定索引的元素),或者中括号里一个列表取多个索引(此时返回的是一个Series类型)。
    s1 = Series(data=[1,2,3],index=['a','b','c'])
    ----> s1[1] 返回的是指定索引的元素
    ----> s1[[0,1]] 返回的是一个Series类型
    显式索引:
    使用index中的元素作为索引值,
    使用s.loc[](推荐):注意,loc中括号中放置的一定是显示索引
    ----> s1.b
    ----> s1.loc["b"]
    隐式索引
    使用.iloc[](推荐):iloc中的中括号中必须放置隐式索引
    ----> s1.iloc[1]

    Series切片:隐式索引切片和显示索引切片
    显示索引切片:index和loc
    s1["a":"c"]根据index切
    s1.loc["a":"c"]根据loc切
    隐示索引切片:整数索引值和iloc
    s1[0:2]根据整数索引值切
    s1.iloc[0:2]根据iloc切

    Series的基本概念
    可以把Series看成一个定长的有序字典
    向Series增加一行:相当于给字典增加一组键值对

    可以通过shapesizeindex,values等得到series的属性

    可以使用s.head(n),tail(n)分别查看前n个和后n个值

    当索引没有对应的值时,可能出现缺失数据显示NaN(not a number)的情况

    可以使用pd.isnull()pd.notnull(),或s.isnull(),notnull()函数检测缺失数据

     
    屏幕快照 2018-11-05 下午8.44.28.png

    Series的运算
    + - * /
    add()/sub()/mul()/div()
    s1.div(s2,fill_value=9)
    在运算中自动对齐不同索引的数据,如果索引不对应,则补NaN

    二、DataFarme(数据帧)

    DataFarme认识
    DataFrame是一个【表格型】的数据结构。DataFrame由按一定顺序排列的多列数据组成。设计初衷是将Series的使用场景从一维拓展到多维。DataFrame既有行索引,也有列索引。
    行索引:index
    列索引:columns
    值:values

    DataFrame(数据帧)的创建
    最常用的方法是传递一个字典来创建。DataFrame以字典的键作为每一【列】的名称,以字典的值(一个数组)作为每一列。
    此外,DataFrame会自动加上每一行的索引。
    使用字典创建的DataFrame后,则columns参数将不可被使用。
    同Series一样,若传入的列与字典的键不匹配,则相应的值为NaN。
    使用字典创建DataFarme
    dict = {"java":[90,22,66],'python':[12,33,66]}
    DataFrame(data=dict,index=['章伞','里斯','魍伍'])
    使用ndarray创建DataFrame
    DataFrame(data=np.random.randint(0,100,size=(3,6)),index=["one","two","three"],columns=["呵","哈","嘿","嘻","嗨","呜"])

    DataFarme属性
    DataFrame属性:values、columns、index、shape

    DataFrame的索引

    对列进行索引
    -- 通过类似字典的方式 df['q']
    -- 通过属性的方式 df.q
    可以将DataFrame的列获取为一个Series。返回的Series拥有原DataFrame相同的索引,且name属性也已经设置好了,就是相应的列名。
    --- df["呵"]
    --- df.呵
    --- df[["呵","哈","嘿"]]
    修改列索引
    df.columns = ['1','2','3',"4","5","6"]

    对行进行索引
    使用.loc[]加index来进行行索引
    使用.iloc[]加整数来进行行索引
    同样返回一个Series,index为原来的columns。
    --- df.loc["one"]
    --- df.loc[["one","two"]]
    --- df.loc["one":"three"]
    --- df["one":"three"]
    --- df["one":"three"]["嘿"]
    修改行索引
    --- df.index = [1,2,3]

    对元素索引的方法
    行索引在前,列索引在后
    --- df.loc["one"]["哈"]
    --- df.iloc[0]["哈"]

    DataFrame的列删除
    df.drop("列名",axio=1,inplace=True)

    DataFarme的切片
    --- df.loc["one":"three","呵":"嘿"]
    --- df.loc["one":"two"][["呵","呜"]]
    --- df.loc["one":"two",["呵","呜","哈"]]
    --- df.loc[["one"],["呵","呜","哈"]]

    DataFrame的运算
    同Series一样:
    在运算中自动对齐不同索引的数据
    如果索引不对应,则补NaN

    处理丢失数据
    有两种丢失数据:None、np.nan(NaN)
    None是Python自带的,其类型为python object。因此,None不能参与到任何计算中。
    np.nan是浮点类型,能参与到计算中。但计算的结果总是NaN。

    pandas中None与np.nan都视作np.nan

    pandas处理空值操作
    isnull(). 判断函数
    notnull() 判断函数
    dropna(): 过滤丢失数据
    df.dropna() 可以选择过滤的是行还是列(默认为行):axis中0表示行,1表示的列
    fillna(): 填充丢失数据
    很多时候将空值全都dropna()掉是不现实的,所以需要用fillna()填充空值。
    df.fillna(value=100) 或者 df.fillna(method="ffill",axis=0)
    method 控制填充的方式,可以选择前向填充还是后向填充

    DataFrame的数据过滤
    df.query(expr, inplace=False, **kwargs),可以指定一个字符串形式的筛选条件 逻辑与& 或 | ==

    df.shift() 该函数主要的功能就是使数据框中数据整体移动
    df.shift(1)

    三、创建多层列索引

    隐式构造
    最常见的方法是给DataFrame构造函数的index或者columns参数传递两个或更多的数组
    df = DataFrame(data=np.random.randint(80,100,size=(2,4)),index=['tom','jay'],columns=[['qz','qz','qm','qm'],['chinese','math','chinese','math']])

    显示构造pd.MultiIndex.from_
    使用数组方式
    创建了一个索引对象,该索引对象为二层索引
    indexObj = pd.MultiIndex.from_arrays([['qz','qz','qm','qm'],['chinese','math','chinese','math']])
    创建DF对象
    DataFrame(data=np.random.randint(80,100,size=(2,4)),index=['tom','jar'],columns=indexObj)

     
    屏幕快照 2018-11-05 下午10.00.20.png

    使用product方式

    最简单,推荐使用
    col=pd.MultiIndex.from_product([['qizhong','qimo'], ['chinese','math']])
    创建DF对象
    df = DataFrame(data=np.random.randint(10,100,size=(2,4)),index=['tom','jay'], columns=col)

     
    屏幕快照 2018-11-05 下午10.05.06.png

    多层行索引
    除了列索引,行索引也能用上述同样的方法创建多层行索引

    多层索引对象的索引与切片操作
    注意在对行索引的时候,若一级行索引还有多个,对二级行索引会遇到问题!也就是说,无法直接对二级索引进行索引,必须让二级索引变成一级索引后才能对其进行索引!

    总结:
    访问一列或多列 直接用中括号[columnname] 、[[columname1,columnname2...]]
    访问一行或多行 .loc[indexname]
    访问某一个元素 .loc[indexname,columnname]
    行切片 .loc[index1:index2]
    列切片 .loc[:,column1:column2]

    聚合操作
    所谓的聚合操作:平均数,方差,最大值,最小值……
    使用value_counts()函数,统计列中各个元素出现次数
    使用unique()函数查看一列中有哪些元素

    四、pandas的拼接操作(类似数据库的联表)

    pandas的拼接分为两种:
    级联:pd.concat, pd.append
    合并:pd.merge, pd.join

    ----级联

    pandas使用pd.concat级联函数,与np.concatenate函数类似,只是多了一些参数:
    objs 级联的对象
    axis=0 轴向
    keys:列表,列表元素表示的是进行级联的df的一个名称
    join='outer' / 'inner':表示的是级联的方式,outer会将所有的项进行级联(忽略匹配和不匹配),而inner只会将匹配的项级联到一起,不匹配的不级联
    ignore_index=False

    匹配级联
    df1 = DataFrame(data=np.random.randint(0,100,size=(3,3)),index=['a','b','c'],columns=['A','B','C'])
    pd.concat([df1,df1],axis=0)
    不匹配级联
    不匹配指的是级联的维度的索引不一致。例如纵向级联时列索引不一致,横向级联时行索引不一致
    不匹配级联有2种连接方式:
    外连接:补NaN(默认模式)
    内连接:只连接匹配的项
    df1 = DataFrame(data=np.random.randint(0,100,size=(3,3)),index=['a','b','c'],columns=['A','B','C'])
    df2 = DataFrame(data=np.random.randint(0,100,size=(3,3)),index=['a','c','d'],columns=['A','C','D'])
    外链接pd.concat([df1,df2],axis=1,join="outer")
    内链接pd.concat([df1,df2],axis=0,join="inner")
    内链接指定keyspd.concat([df1,df2],axis=1,join="inner",keys=['AAA','BBB'])

    df.append()函数级联
    由于在后面级联的使用非常普遍,因此有一个函数append专门用于在后面添加
    df1.append(df2)

    ----合并

    使用pd.merge()合并
    merge与concat的区别在于,merge需要依据某一共同的列来进行合并
    使用pd.merge()合并时,会自动根据两者相同column名称的那一列,作为key来进行合并。
    注意每一列元素的顺序不要求一致

    参数
    how:out取并集 inner取交集
    on:当有多列相同的时候,可以使用on来指定使用那一列进行合并,on的值为一个列表
    一对一合并
    df1 = DataFrame({'employee':['Bob','Jake','Lisa'],'group':['Accounting','Engineering','Engineering'],})
    df2 = DataFrame({'employee':['Lisa','Bob','Jake'],'hire_date':[2004,2008,2012],})
    merge合并:pd.merge(df1,df2)
    多对一合并
    df3 = DataFrame({'employee':['Lisa','Jake'],'group':['Accounting','Engineering'],'hire_date':[2004,2016]})
    df4 = DataFrame({'group':['Accounting','Engineering','Engineering'],'supervisor':['Carly','Guido','Steve']})
    pd.merge(df3,df4)
    多对多合并

    key的规范化使用
    当列冲突时,即有多个列名称相同时,需要使用on=来指定哪一个列作为key,配合suffixes指定冲突列名。
    pd.merge(df1,df2,on="group",suffixes=('_甲','乙'),how="outer")

    注意:当两张表没有可进行连接的列时,可使用left_on和right_on手动指定merge中左右两边的哪一列列作为连接的列

    内合并与外合并:
    外合并outer:取并集,补NaN
    内合并inner:取交集,保留两者都有的key

    五、pandas数据处理

    1、检测重复行 duplicated()
      使用duplicated()函数检测重复的行,返回元素为布尔类型的Series对象,每个元素对应一行,如果该行不是第一次出现,则元素为True
    keep参数:指定保留哪一重复的行数据
    True 重复的行

    2.删除重复行 drop_duplicates()
      使用drop_duplicates()函数删除重复的行
      drop_duplicates(keep='first/last'/False)

    2. 映射:指定替换
      replace()函数:替换元素
      使用replace()函数,对values进行映射操作

    Series替换操作replace()
    单值替换
      普通替换
      s.replace(to_replace=2,value='two',inplace=True)
      字典替换(推荐)
      s.replace(to_replace={2:'two'},inplace=True)
    多值替换
      列表替换
      s.replace(to_replace=[1,5],value=['one','five'])
      字典替换(推荐)
      s.replace(to_replace={3:'three',4:'four'},inplace=True)
    参数
      to_replace:被替换的元素
      method:对指定的值使用相邻的值填充替换
      limit:设定填充次数

    DataFrame替换操作
    单值替换
      普通替换: 替换所有符合要求的元素,没有要替换的值也不会报错:
      df.replace(to_replace=64,value='aaa')
      按列指定单值替换: to_replace={列标签:替换值} ,value='value'
      df.replace(to_replace={2:85},value='eight')
    多值替换
      列表替换: to_replace=[] value=[]
      df.replace(to_replace=[9,0],value=['a','b'])
      字典替换(推荐) to_replace={to_replace:value,to_replace:value}
      df.replace(to_replace={1:"one",30:"thirty"})
    注意:DataFrame中,无法使用method和limit参数

    3. map()函数:新建一列
      map是Series的一个函数
      map()可以映射新一列数据
      map()中可以使用lambd表达式
      map()中可以使用方法,可以是自定义的方法
    注意 map()中不能使用sum之类的函数,for循环
    df = DataFrame(data=[['zhangsan',1000,'sale'],['lisi',2000,'dev'],['wangwu',3333,'dev']],columns=['name','salary','dep'])
    增加名为e_name列:
    df['e_name'] = df['name'].map({'lisi':'Tony','zhangsan':'Tom','wangwu':'Jerry'})

    map当做一种运算工具,至于执行何种运算,是由map函数的参数决定的
    (参数:lambda,函数)

    -- 使用自定义函数
      def func():
        ...
        return xxx
      df['salary'].map(func)
    -- 使用lambda表达式
      df['salary'].map(lamada x:x..)

    注意:并不是任何形式的函数都可以作为map的参数。只有当一个函数具有一个参数且有返回值,那么该函数才可以作为map的参数。

    4. 使用聚合操作对数据异常值检测和过滤
    使用df.std()函数可以求得DataFrame对象每一列的标准差
    此处不再做详细解读

    5. 排序
    --使用sort_value()排序
    d f.sort_values(by="列名",axis=0,ascending=False)
    -- 使用.take()函数排序
    take()函数接受一个索引列表,用数字表示,使得df根据列表中索引的顺序进行排序
    df.take([1,2,0],axis=0)

     
    屏幕快照 2018-11-06 下午8.14.29.png

    -- 可以借助np.random.permutation()函数随机排序
    np.random.permutation(x)可以生成x个从0-(x-1)的随机数列
    arr = np.random.permutation(4)
    df.take(arr,axis=1)
    随机抽样:当DataFrame规模足够大时,直接使用np.random.permutation(x)函数,就配合take()函数实现随机抽样

    6.数据分类处理【重点】
    数据聚合是数据处理的最后一步,通常是要使每一个数组生成一个单一的数值。

    数据分类处理:
      分组:先把数据分为几组
      用函数处理:为不同组的数据应用不同的函数以转换数据
      合并:把不同组得到的结果合并起来
    数据分类处理的核心:
      groupby()函数
      groups属性查看分组情况
    分组后的聚合操作:分组后的成员中可以被进行运算的值会进行运算,不能被运算的值不进行运算

    unstack()与reset_index()对比:
    针对多列分组情况,使用unstack(level=1)将上面所得分组数据指定的索引变成列索引。

     
    屏幕快照 2018-11-07 下午4.05.50.png

    把索引变成列,Series.reset_index()
     
    屏幕快照 2018-11-07 下午4.16.23.png

    pandas数据读取和写入:

    1.pandas提供了一些用于将表格型数据读取为DataFrame对象的函数,期中read_csv和read_table这两个使用最多。
    2.使用read_csv读取url获取网络上的数据
    3.通过to_excel(path)、to_sql("sql语句",conn)等方式将数据写入对应的文件或数据库

  • 相关阅读:
    Linux并发与同步专题 (1)原子操作和内存屏障
    Linux并发与同步专题
    功耗案例分析:周期性底电流抬高问题分析和解决
    Android OpenGL 基础入门
    使用Codeblock搭建Windows下Objec-c学习环境
    Muduo 多线程模型对比
    NPTL 线程同步方式
    C++ 封装互斥对象
    Java 常用字符串操作总结
    Android 开发有用代码积累
  • 原文地址:https://www.cnblogs.com/john-xiong/p/11854721.html
Copyright © 2011-2022 走看看