美文网首页
2020-08-02--Pandas-01--常用数据结构

2020-08-02--Pandas-01--常用数据结构

作者: program_white | 来源:发表于2020-08-04 16:21 被阅读0次

    Pandas概述

    Pandas(Python Data Analysis Library )是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。Pandas提供了大量能使我们快速便捷地处理数据的函数和方法。你很快就会发现,它是使Python成为强大而高效的数据分析环境的重要因素之一。

    Pandas是Python的一个数据分析包,最初由AQR Capital Management于2008年4月开发,并于2009年底开源出来,目前由专注于Python数据包开发的PyData开发team继续开发和维护,属于PyData项目的一部分。Pandas最初被作为金融数据分析工具而开发出来。

    Pandas含有使数据分析工作变得更快更简单的高级数据结构和操作工具。pandas是基于Numpy构建的,让以Numpy为中心的应用变得更简单。

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

    • Pandas是2008年Wes McKinney于AQR资本做量化分析师时创建
    • Pandas借鉴了R的数据结构
    • Pandas基于Numpy搭建,支持Numpy中定义的大部分计算
    • Pandas含有使数据分析工作更简单高效的高级数据结构和操作工具
    • Pandas底层用Cython和C做了速度优化,极大提高了执行效率

    Pandas 有很多高级的功能,但是想要掌握高级功能前,需要先掌握它的基础知识,Pandas 中的数据结构算是非常基础的知识之一了。

    Pandas 常用的数据结构有两种:SeriesDataFrame。这些数据结构构建在 Numpy 数组之上,这意味着它们效率很高。我们来分别看看这些数据结构都长什么样子吧。

    # 导入相关库
    import numpy as np
    import pandas as pd
    

    Series

    1.简介,创建Series基本结构

    Series 是一个带有 名称 和索引的一维数组,既然是数组,肯定要说到的就是数组中的元素类型,在 Series 中包含的数据类型可以是整数、浮点、字符串、Python对象等。
    假定有一个场景是:存储一些用户的信息,暂时只包括年龄信息。

    我们可以通过 Series 来存储,这里我们通过 Series 存储了四个年龄:18/30/25/40,只需将要存储的数据构建成一个数组,然后赋值给data参数即可。

    import pandas as pd
    
    user_age = pd.Series(data=[18,30,25,40])
    print(type(user_age))                # <class 'pandas.core.series.Series'>
    print(user_age)
    # 0    18
    # 1    30
    # 2    25
    # 3    40
    # dtype: int64
    
    # 支持多种基本数据类型
    user_age = pd.Series(data=[18,30,'25岁',40])
    print(type(user_age))                # <class 'pandas.core.series.Series'>
    print(user_age)
    # 0     18
    # 1     30
    # 2    25岁
    # 3     40
    # dtype: object
    

    并且可以看出,Series中的数据支持多种数据类型,它会自动识别其中数据的数据类型。

    可以看到,已经正确将多个年龄存储到 Series 中了,你可能会想,单独存储了年龄有什么用,我怎么知道这个年龄属于哪个用户呢?

    我们可以通过 Series 的 index(索引)来解决这个问题。由于有四个年龄,自然地也需要四个姓名,所以我们需要构建一个与 data 长度相同的数组,然后通过下面的操作即可满足要求。

    # 设置索引
    user_age.index = ['zhangsan','lisi','wangwu','zhaoliu']
    print(user_age)
    # zhangsan     18
    # lisi         30
    # wangwu      25岁
    # zhaoliu      40
    # dtype: object
    

    你看,现在姓名与年龄已经完全对应上了。虽然说我们自己知道 Tom/Bob 这些是姓名,但是别人不知道啊,我们怎么告诉他人呢?

    要想让别人知道,我们可以为 index 起个总名字,类似于表格的样子。

    # 为索引设置name
    user_age.index.name = 'name'
    print(user_age)
    # name
    # zhangsan     18
    # lisi         30
    # wangwu      25岁
    # zhaoliu      40
    # dtype: object
    

    可能你还会想,如果别人在看我写的代码,怎么能快速的知道我这写的到底是什么玩意呢?

    别急,就像我们给index起名字一样,我们也可以给 整个Series 起个总名字。

    # 为Series设置name
    user_age.name = 'user_age_info'
    print(user_age)
    # name
    # zhangsan     18
    # lisi         30
    # wangwu      25岁
    # zhaoliu      40
    # Name: user_age_info, dtype: object
    

    通过上面一系列的操作,我们对 Series 的结构上有了基本的了解,
    简单来说,一个 Series 包括了:

    • data :对应Series对象的数据。
    • index:Series对象数据的索引,在索引上也有name属性, 默认索引为RangeIndex(start=0, stop=4, step=1):0,1,2,3。name属性不设置时,默认返回None。
    • name:整个Series对象的名称。没设置时,返回None。

    上面的操作非常方便做演示来使用,如果想要快速实现上面的功能,可以通过以下方式来实现。

    2.快速创建Series基本结构

    创建索引信息:数据和name:

    • 在pd.Index(data=[],name=)
      创建Series对象:data,索引index,name属性,dtype数据类型(不写自动推断)
    • 在pd.Series(data=[],index=,name=,dtype=)
    # 快速创建Series基本结构
    name = pd.Index(['zhangsan','lisi','wangwu','zhaoliu'],name='姓名')
    age = [18,30,'25岁',40]
    user = pd.Series(data=age,index=name,name='user_age')
    print(user)
    # 姓名
    # zhangsan     18
    # lisi         30
    # wangwu      25岁
    # zhaoliu      40
    # Name: user_age, dtype: object
    

    需要说明的是我们在构造 Series 的时候,并没有设定每个元素的数据类型,这个时候,Pandas 会自动判断一个数据类型,并作为 Series 的类型。

    当然了,我们也可以自己手动指定数据类型。

    user_age = pd.Series(data=[18, 30, 25, 40], index=name, name="user_age_info", dtype=float)
    print(user_age)
    # 姓名
    # zhangsan    18.0
    # lisi        30.0
    # wangwu      25.0
    # zhaoliu     40.0
    # Name: user_age_info, dtype: float64
    

    3.Series 像什么(数据获取)

    Series 包含了 dict 的特点,也就意味着可以使用与 dict 类似的一些操作。我们可以将 index 中的元素看成是 dict 中的 key。
    两种方式获取数据,与dict中获取数据一样:

    # 获取数据,注意user时Series对象,而不是Series对象的name属性值
    age =user['zhangsan']
    print(age,type(age))
    # 18 <class 'int'>
    
    age = user.get('lisi')
    print(age,type(age))
    # 30 <class 'int'>
    

    Series 除了像 dict 外,也非常像 ndarray,这也就意味着可以采用切片操作。

    • 下标获取单个元素-------user[1]
    • 下标获取多个元素-------[[1,3]]
    • 切片获取-----------user[:3]
    • 花式索引----------user[表达式(返回bool值数组)]
    # 通过数组下标的方式获取数据
    age = user[0]
    print(age)
    # 18
    
    # 切片操作,返回Series对象
    age = user[:3]
    print(age)
    # 姓名
    # zhangsan     18
    # lisi         30
    # wangwu      25岁
    # Name: user_age, dtype: object
    
    # 花式索引--索引为表达式:该表达式返回一个都为bool值的数组
    # 返回Series对象
    age = user[user>20]
    print(age)
    # 姓名
    # lisi       30.0
    # wangwu     25.0
    # zhaoliu    40.0
    # Name: user_age_info, dtype: float64
    
    # 获取多个元素--第二个元素和最后一个元素
    age = user[[1,3]]
    print(age)
    # 姓名
    # lisi       30.0
    # zhaoliu    40.0
    # Name: user_age_info, dtype: float64
    

    总结:
    也就是说:Series对象获取元素可以像字典一样通过key获取,也可以像pythonlist和ndarray一样通过下标,切片,花式索引获取数据。
    当然也可以获取到元素后,就可以操作元素了,例如改变元素的值。

    4.Series 的向量化操作

    Series 与 ndarray 一样,也是支持向量化操作的。同时也可以传递给大多数期望 ndarray 的 NumPy 方法。

    # 向量操作
    print(user)
    # 姓名
    # zhangsan    18.0
    # lisi        30.0
    # wangwu      25.0
    # zhaoliu     40.0
    # Name: user_age_info, dtype: float64
    # 数据整体加一
    user_add = user+1
    print(user_add)
    # 姓名
    # zhangsan    19.0
    # lisi        31.0
    # wangwu      26.0
    # zhaoliu     41.0
    # Name: user_age_info, dtype: float64
    
    exp = np.exp(user)
    print(exp)
    # 姓名
    # zhangsan    6.565997e+07
    # lisi        1.068647e+13
    # wangwu      7.200490e+10
    # zhaoliu     2.353853e+17
    # Name: user_age_info, dtype: float64
    

    DataFrame

    1.DataFrame的创建

    DataFrame 是一个带有索引的二维数据结构,每列可以有自己的名字,并且可以有不同的数据类型。你可以把它想象成一个 excel 表格或者数据库中的一张表,DataFrame 是最常用的 Pandas 对象。

    我们继续使用之前的实例来讲解 DataFrame,在存储用户信息时,除了年龄之外,我还想存储用户所在的城市。如何通过 DataFrame 实现呢?

    可以构建一个 dict,key 是需要存储的信息,value 是信息列表。然后将 dict 传递给 data 参数。

    import pandas as pd
    
    # 创建索引
    index = pd.Index(data=["Tom", "Bob", "Mary", "James"], name="name")
    
    # 数据
    data = {
        "age": [18, 30, 25, 40],
        "city": ["BeiJing", "ShangHai", "GuangZhou", "ShenZhen"]
    }
    # 创建DataFrame对象
    user_info = pd.DataFrame(data=data, index=index)
    print(user_info)
    #         age       city
    # name
    # Tom     18    BeiJing
    # Bob     30   ShangHai
    # Mary    25  GuangZhou
    # James   40   ShenZhen
    print(type(user_info))
    # <class 'pandas.core.frame.DataFrame'>
    

    可以看到,我们成功构建了一个 DataFrame,这个 DataFrame 的索引是用户姓名,还有两列分别是用户的年龄和城市信息。

    除了上面这种传入 dict 的方式构建外,我们还可以通过另外一种方式来构建。这种方式是先构建一个二维数组,然后再生成一个列名称列表。

    
    # 创建索引
    index = pd.Index(data=["Tom", "Bob", "Mary", "James"], name="name")
    data = [[18, "BeiJing"],
            [30, "ShangHai"],
            [25, "GuangZhou"],
            [40, "ShenZhen"]]
    columns = ["age", "city"]
    
    user_info = pd.DataFrame(data=data, index=index, columns=columns)
    print(user_info)
    #        age       city
    # name
    # Tom     18    BeiJing
    # Bob     30   ShangHai
    # Mary    25  GuangZhou
    # James   40   ShenZhen
    

    总结:pd.DataFrame(data=数据,index=行的表识(其中有name属性),columns=列标识)
    pd.Index(data=[索引数据项],name=数据名)

    2.访问行

    在生成了 DataFrame 之后,可以看到,每一行就表示某一个用户的信息,假如我想要访问 Tom 的信息,我该如何操作呢?

    一种办法是通过索引名来访问某行,这种办法需要借助 loc 方法。
    user.loc[index]

    # 访问行
    tom = user_info.loc['Tom']
    print(tom)
    # age          18
    # city    BeiJing
    # Name: Tom, dtype: object
    print(type(tom))
    # <class 'pandas.core.series.Series'>
    

    获取多个元素可以使用索引切片的方式获取:

    # 访问行
    tom = user_info.loc['Tom':]
    print(tom)
    #        age       city
    # name                 
    # Tom     18    BeiJing
    # Bob     30   ShangHai
    # Mary    25  GuangZhou
    # James   40   ShenZhen
    print(type(tom))
    # <class 'pandas.core.frame.DataFrame'>
    

    除了直接通过索引名来访问某一行数据之外,还可以通过这行所在的位置来选择这一行。
    user.iloc[0]

    tom = user_info.iloc[0]
    print(tom)
    # age          18
    # city    BeiJing
    # Name: Tom, dtype: object
    print(type(tom))
    # <class 'pandas.core.series.Series'>
    

    借助行切片可以轻松完成,来看这里。
    切片访问:

    # 切片访问
    user = user_info.iloc[:3]
    print(user)
    #       age       city
    # name                
    # Tom    18    BeiJing
    # Bob    30   ShangHai
    # Mary   25  GuangZhou
    print(type(user))
    # <class 'pandas.core.frame.DataFrame'>
    

    当访问一条数据信息时,返回的类型为Series类型,多条时返回DataFrame类型。

    2.访问列

    学会了如何访问行数据之外,自然而然会想到如何访问列。我们可以通过属性(“.列名”)的方式来访问该列的数据,也可以通过[column]的形式来访问该列的数据。

    假如我想获取所有用户的年龄,那么可以这样操作。
    user.age
    user['age']

    # 访问列
    print(user.age)
    print(user['age'])
    # name
    # Tom     18
    # Bob     30
    # Mary    25
    # Name: age, dtype: int64
    print(type(user.age))      # <class 'pandas.core.series.Series'>
    

    如果想要同时获取年龄和城市该如何操作呢?

    # 多值
    print(user[['age','city']])
    #       age       city
    # name
    # Tom    18    BeiJing
    # Bob    30   ShangHai
    # Mary   25  GuangZhou
    print(type(user[['age','city']]))   # # <class 'pandas.core.frame.DataFrame'>
    

    3.新增/删除行

    在生成了 DataFrame 之后,突然你发现好像缺失了用户的性别这个信息,那么如何添加呢?

    如果所有的性别都一样,我们可以通过传入一个标量,Pandas 会自动帮我们广播来填充所有的位置。

    # 新增列
    user['sex'] = '男'
    print(user)
    #       age       city sex
    # name
    # Tom    18    BeiJing   男
    # Bob    30   ShangHai   男
    # Mary   25  GuangZhou   男
    

    如果想要删除某一列,可以使用 pop 方法来完成。

    # 删除列
    user.pop('sex')
    print(user)
    #       age       city
    # name                
    # Tom    18    BeiJing
    # Bob    30   ShangHai
    # Mary   25  GuangZhou
    

    如果用户的性别不一致的时候,并且数据量不是很大时,我们可以通过传入一个 list 来添加新的一列:

    # 设置不同的sex
    user['sex'] = ['男','女','女']
    print(user)
    #       age       city sex
    # name                    
    # Tom    18    BeiJing   男
    # Bob    30   ShangHai   女
    # Mary   25  GuangZhou   女
    

    通过上面的例子可以看出,我们创建新的列的时候都是在原有的 DataFrame 上修改的,也就是说如果添加了新的一列之后,原有的 DataFrame 会发生改变。

    如果想要保证原有的 DataFrame 不改变的话,我们可以通过 assign 方法来创建新的一列。返回一个新的DataFrame对象。

    # 创建新的一列,该列的值为每一行中的age+1
    user2 = user.assign(age_add_one=user['age']+1)
    print(user2)
    #       age       city sex  age_add_one
    # name                                 
    # Tom    18    BeiJing   男           19
    # Bob    30   ShangHai   女           31
    # Mary   25  GuangZhou   女           26
    

    还有一种就是根据已有列的值不同,来创建新的列的值。

    print(user)
    #       age       city sex
    # name
    # Tom    18    BeiJing   男
    # Bob    30   ShangHai   女
    # Mary   25  GuangZhou   女
    # 新建一列avail,该列的值由每列的age决定,若age大于18,则该列的值为有效,否则为无效。
    user3 = user.assign(avail=np.where(user['age']>18,'有效','无效'))
    print(user3)
    #       age       city sex avail
    # name
    # Tom    18    BeiJing   男    无效
    # Bob    30   ShangHai   女    有效
    # Mary   25  GuangZhou   女    有效
    

    相关文章

      网友评论

          本文标题:2020-08-02--Pandas-01--常用数据结构

          本文链接:https://www.haomeiwen.com/subject/rtwprktx.html