• 数据分析之pandas入门读书笔记


    前言

    之前,我已经通过笔记记录的方式把python的基础部分全部学习完成,欢迎大家移步我的python基础专栏。

    学完了基础,也对python有了了解,如果你让我重新学习一门语言,也不是不可以,比如Java,也有专栏哦,但是我感觉python已经刻在了我的DNA里面,也就了解了大数据,数据分析。同时这也是我自己选择的专业。正在学习中。

    课上老师讲的知识,如果我不在课下复习,那么我会更快忘记,更何况python我感觉都是由函数组成,记不住函数,还学什么。

    课下看的是《利用Python进行数据分析·第2版》写成电子版的读书笔记。加深记忆

    由此一来,也可以督促自己提升效率

    pandas入门

    首先应该了解什么是pandas,用来对数据进行分析和清洗的工具包,经常与NumPy、SciPy、statsmodels等等第三方库使用,

    经常可以看的pandas与numpy一起使用,一开始我也是以为两者区别很小,错了,有的很大的区别

    虽然pandas采用了numpy的编码风格但是pandas是用来处理表格数据和混杂数据,而numpy适合做数值数组处理。

    因为已经熟悉了numpy,他提出了array,也有大量的函数、求绝对值、平方,统计等等,这就是对一个数组的统计。

    而pandas,我已经学习过一周,它更像一个表格,有行标签和列标签。

    pandas的引入约定

    import pandas as pd
    
    • 1

    也可以这样

    from pandas import Series, DataFrame
    
    • 1

    因为Series, DataFrame这两个非常常用

    pandas的数据结构介绍

    上面说过了Series, DataFrame非常常用,同时这也是pandas的数据结沟

    Series

    Series是一种类似于一维数组的对象,它由一组数据(各种NumPy数据类型)以及 一组与之相关的数据标签(即索引)组成。仅由一组数据即可产生最简单的 Series

    这就可以理解为一维数据的表现形式,有一组数据和数据标签组成

    s = pd.Series([1,2,3,4,5])  # 列表创建
    s
    
    • 1
    • 2
    0    1
    1    2
    2    3
    3    4
    4    5
    dtype: int64
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    左边是索引,右边是值,因为没有专门指定索引,所以就自动是,从0到N-1(数组长度-1)

    下面还标记了数据的类型int64

    可以通过valuesindex属性查看数组表示形式和索引对象

    s.values
    ## array([1, 2, 3, 4, 5], dtype=int64)
    
    • 1
    • 2

    这是数组的表现形式,就是看看数据是什么。

    s.index
    ## RangeIndex(start=0, stop=5, step=1)
    
    • 1
    • 2

    这个是索引的属性,应该是pandas的属性,从0开始,4结束,步长1

    也可以对每个数据标记索引,自定义索引

    # 自定义索引
    import numpy as np
    arr = np.arange(5)
    idx = ['e','d','c','b','a']
    s2 = pd.Series(arr, index=idx)
    s2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    e    0
    d    1
    c    2
    b    3
    a    4
    dtype: int32
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    再来看这个索引,就和上面的不一样了,上面的是一个12345的序列,自动所生成的,而我的这个是edcba,自定义的

    同时注意看我用到了np.arange()函数,数组也可以创建Series类型。后面还有字典也可以。

    s2.index
    ## Index(['e', 'd', 'c', 'b', 'a'], dtype='object')
    
    • 1
    • 2

    s2的索引属性怎么看呢,和上面的不一样,这是一个python的对象类型,应该是这样,

    然后也可以索引

    s2['c']
    ## 2
    
    • 1
    • 2

    这就是一个索引,没别的可说。

    s2['b'] = 30
    s2[['c', 'b', 'd']]
    
    • 1
    • 2
    c     2
    b    30
    d     1
    dtype: int32
    
    • 1
    • 2
    • 3
    • 4

    数据进行修改,

    s2[['c', 'b', 'd']]类似numpy里的花式索引。

    numpy学完了并不是没有用,这里就可以用到numpy的函数或者运算、布尔过滤、标量乘法、应用数学等等

    # 布尔计算
    s2[s2>3]
    
    • 1
    • 2
    b    30
    a     4
    dtype: int32
    
    • 1
    • 2
    • 3

    找出大于3的元素

    # 计算
    s2 * 2
    
    • 1
    • 2
    e     0
    d     2
    c     4
    b    60
    a     8
    dtype: int32
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    对每个数据乘以2

    # numpy函数
    np.exp(s2)
    
    • 1
    • 2
    e    1.000000e+00
    d    2.718282e+00
    c    7.389056e+00
    b    1.068647e+13
    a    5.459815e+01
    dtype: float64
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    np.exp()是一个numpy里的函数。

    Series可以看成是一个字典,因为和字典大致相同,是索引值和数据值的映射,所以也可以用需要字典参数的函数

    'b' in s2
    ## True
    
    • 1
    • 2
    'y' in s2
    ## False
    
    • 1
    • 2

    说到了字典,数据存放在字典里面也是可以创建Series,

    data_dict = {"小明": 95, "小刚": 75, "小红": 90, "张三": 70, "李四": 67}
    s3 = pd.Series(data_dict)
    s3
    
    • 1
    • 2
    • 3
    小明    95
    小刚    75
    小红    90
    张三    70
    李四    67
    dtype: int64
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    不指定索引标签的话,会发现,字典的键就是Series索引,字典的值也是Series的值。有序排列,字典是什么顺序,则Series也是什么顺序。

    也可以指定一个index,传入一个排好序的字典的键改变顺序。

    idx = ["小红", "小明", "李四", "王五", "小刚"]
    s4 = pd.Series(data_dict, index=idx)
    s4
    
    • 1
    • 2
    • 3
    小红    90.0
    小明    95.0
    李四    67.0
    王五     NaN
    小刚    75.0
    dtype: float64
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里我踩个坑,一开始我因为直接改变了Series的额标签,不是这样的,是改变了顺序。在字典中,小红对应90,那么现在小红还是90,只不过上面小红在第三个,这个是第一。

    NaN是什么?缺失数据,非数字(not a number)

    因为字典中没有王五的数据,所以结果就是NaN,

    pandas提供了两个函数用来检测缺失数据isnull()notnull()

    pd.isnull(s4)
    
    • 1
    小红    False
    小明    False
    李四    False
    王五     True
    小刚    False
    dtype: bool
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    pd.notnull(s4)
    
    • 1
    小红     True
    小明     True
    李四     True
    王五    False
    小刚     True
    dtype: bool
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    这两个函数我感觉很好区分

    isnoll()是缺失数据的数据,王五是缺失数据,所以True,其他的不是不是缺失数据,False

    notnull()不是缺失数据的数据,与上面反过来。

    如果两个或多个Series进行运算,索引标签会自动对齐数据。

    s3 + s4
    
    • 1
    小刚    150.0
    小明    190.0
    小红    180.0
    张三      NaN
    李四    134.0
    王五      NaN
    dtype: float64
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    就用上面已经创建好的s3和s4举例,让他们相加。

    因为用的是同一个字典数据,小刚75,那么75+75=150。相加后新的Series就是小刚150。

    标签自动对齐数据。虽然标签顺序不同,但是相加的时候还是会

    Series得得索引标签有一个name属性,就是给索引标签指定一个属性。

    s4.name = "students name"
    s4
    
    • 1
    • 2
    小红    90.0
    小明    95.0
    李四    67.0
    王五     NaN
    小刚    75.0
    Name: students name, dtype: float64
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    给标签设置一个名字,这里有一个有意思的一点,.name=""是设置名字,那么.name就是查看名字

    s4.name
    ## 'students name'
    
    • 1
    • 2

    index属性也可以

    s
    
    • 1
    0    1
    1    2
    2    3
    3    4
    4    5
    dtype: int64
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    修改他的索引

    s.index = ['v','w','x','y','z']
    s
    
    • 1
    • 2
    v    1
    w    2
    x    3
    y    4
    z    5
    dtype: int64
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    小结

    到这里,pandas的第一个数据结构就算是一个入门,Series。可以看作是对一维序列的一个演变,由标签索引和数据组成。

    然后说到了他的索引和切片,这个和python字典的差不多,s['a']或者s[1]

    又提到了布尔运算,数学乘法,和numpy的函数一起用,

    两个或多个Series相加数据会根据标签自动对齐。

    两个属性,.name:查看索引名称,.index查看索引或者重新指定索引,.values查看数据

    忘说了Series的创建,可以是列表、数组,字典。

    DataFrame

    这是一个表格型数据结构。有行索引也有列索引。这么说有点别扭,通过与Series进行比较就会很容易发现

    Series是由一个索引标签+数据组成的,那么,DataFrame就是两个索引+数据, 表格型数据结构,一个电子表格就是有行有列的。

    数据的类型和Series的数据类型都有所也有的。

    现在就创建一个DataFram

    import numpy as np
    import pandas as pd
    
    data = {"姓名":["小明","小红","小刚","张三","李四","小王","小玉"],
           "语文":[85,95,60,77,90,85,90],
           "数学":[91,75,70,51,80,75,80]}
    df = pd.DataFrame(data)
    df
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
        姓名  语文  数学
    0	小明	85	91
    1	小红	95	75
    2	小刚	60	70
    3	张三	77	51
    4	李四	90	80
    5	小王	85	75
    6	小玉	90	80
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    如果是在jupyter里面,会生成一个很漂亮的表格

    这个就是表格型结构,有表头、也有列。因为没有指定列索引,所以自动生成

    如果是特别大的数据,可以用.head()来查看前五行数据

    df.head()
    
    • 1
    	姓名	语文	数学
    0	小明	85	91
    1	小红	95	75
    2	小刚	60	70
    3	张三	77	51
    4	李四	90	80
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    指定一个列排列

    pd.DataFrame(data, columns=["数学", "姓名","语文"])
    
    • 1
    	数学	姓名	语文
    0	91	小明	85
    1	75	小红	95
    2	70	小刚	60
    3	51	张三	77
    4	80	李四	90
    5	75	小王	85
    6	80	小玉	90
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    如果传入的列在列表中找不到,那么就会产生缺失值

    同时,我也可以指定行标签

    pd.DataFrame(data, columns=["姓名","语文","数学","英语"],
                index=["one","two","three","four","five","six","seven"])
    
    • 1
    • 2
    	    姓名	语文	数学	英语
    one	    小明	85	91	NaN
    two	    小红	95	75	NaN
    three	小刚	60	70	NaN
    four	张三	77	51	NaN
    five	李四	90	80	NaN
    six	    小王	85	75	NaN
    seven	小玉	90	80	NaN
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    列标签中多了个英语,但是他们没有英语成绩,所以产生缺失值

    index制定了他们的行索引。

    通过类似字典标记的方式或属性的方式,可以将DataFrame的列获取为一个 Series:

    就是获取DataFrame的一列数据

    ## 字典方式
    df["数学"]
    
    • 1
    • 2
    0    91
    1    75
    2    70
    3    51
    4    80
    5    75
    6    80
    Name: 数学, dtype: int64
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    ## 属性方式
    df.姓名
    
    • 1
    • 2
    0    小明
    1    小红
    2    小刚
    3    张三
    4    李四
    5    小王
    6    小玉
    Name: 姓名, dtype: object
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    会发现返回的类型和Series是一样的。

    上面的在学习中会发现是用一个字典创建的,数据的形式中还有一种,嵌套字典。

    dict2 = {"小明":{"语文":80, "数学":85, "英语":77, "物理":88},
            "小红":{"语文":90, "数学":80, "英语":87, "地理":80},
            "小刚":{"语文":85, "数学":66, "英语":69, "化学":77}}
    df3 = pd.DataFrame(dict2)
    df3
    
    • 1
    • 2
    • 3
    • 4
    • 5
         小明	    小红	  小刚
    语文	80.0	90.0	85.0
    数学	85.0	80.0	66.0
    英语	77.0	87.0	69.0
    物理	88.0	NaN	    NaN
    地理	NaN	    80.0	NaN
    化学	NaN	    NaN	    77.0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    阔以得出结论

    外层字典的键作为列,内层 键则作为行索引:

    小明、小红、小明是外层字典的键,成为了列标签,而那些课程属于内层标签,成为了行标签。

    df3.T
    
    • 1
    语文数学英语物理地理化学
    小明80.085.077.088.0NaNNaN
    小红90.080.087.0NaN80.0NaN
    小刚85.066.069.0NaNNaN77.0

    我这才发现是不是用这种表格的方式表达 比较好。

    在numpy中.T是转置的意思,在pandas中竟然也可以用。

     pd.DataFrame(dict2, index=["数学","语文","化学"])
    
    • 1
    小明小红小刚
    数学85.080.066
    语文80.090.085
    化学NaNNaN77

    如果是指定了索引,那么就会安照索引排列

    类型说明
    二维ndarray数据矩阵,还可以传入行标和列彪
    由数组、列彪或元组组成的字典每个序列会变成DataFrame的一列,所有序列的长度必须相同
    NumPy的结构化/记录数组类似于“由数组组成的字典”
    由Series组成的字典每个Series会成为一列,如果没有显式指定索引,则各个Series的索引会被合并成结果的行索引
    由字典组成的字典各内层字典会成为一列,键会被合并成结果的行索引,跟“由Series组成的字典”的情况一样
    字典或Series的列表各项会成为DataFrame的一会,字典的键或Serires索引值的并集会成DataFrame的列标
    由列标或元组组成的列表类似于“二维ndarray”
    另一个DataFrame改DataFrame的索引将会被沿用,除非显式的指定了其他索引
    NumPy的MaskedArray类似于“二维ndarray”的情况,只是掩码值在结果DataFrame会变成NAN缺失值

    就是说这些类型的数据都可以构成DataFrame

    如果在创建时设置了DataFrame的index和columns的name属性值,那么我们就可以查看这些属性。.index.name.columns.name

    如果没有设定,那就需要.index.name=" ".columns.name=" "

    因为在创建时,没有的设置

    df3.index.name = "课程"
    df3.columns.name = "姓名"
    df3
    
    • 1
    • 2
    • 3
    姓名	小明	  小红	 小刚
    课程			
    语文	80.0	90.0	85.0
    数学	85.0	80.0	66.0
    英语	77.0	87.0	69.0
    物理	88.0	NaN	    NaN
    地理	NaN	    80.0	NaN
    化学	NaN	    NaN	    77.0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    df3.index.name
    ## '课程'
    
    • 1
    • 2

    设置一个name属性,就可以通过df3.index.name查出来了

    还有一个.values属性

    df3.values
    
    • 1
    array([[80., 90., 85.],
           [85., 80., 66.],
           [77., 87., 69.],
           [88., nan, nan],
           [nan, 80., nan],
           [nan, nan, 77.]])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    和Serirs一样,只不过返回的是二维数组

    以上就是DataFrame的介绍

    索引对象

    学习了pandas的Series和DataFrame的数据结构,他们有一个共同点,那就是索引。索引是什么,注意,这里的索引和索引切片不是一个东西,

    pandas的索引对象负责管理轴标签和其他元数据(比如轴名称等)。构建Series或 DataFrame时,所用到的任何数组或其他序列的标签都会被转换成一个Index:

    可以不指定索引,那么他会自动生成。

    但我没搞懂负责管理轴标签和其他元数据。

    往下看书中的例子

    import numpy as np
    import pandas as pd
    
    s = pd.Series(np.arange(3), index=['a','b','c'])
    idx = s.index
    idx
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    Index(['a', 'b', 'c'], dtype='object')
    
    • 1

    这是我指定了索引。

    idx[1:]
    
    • 1
    Index(['b', 'c'], dtype='object')
    
    • 1

    可以对索引进行索引。

    但是不可以修改索引

    idx[1] = 'd'
    ## TypeError: Index does not support mutable operations
    
    • 1
    • 2

    不可变可以使Index对象在多个数据结构之间安全共享:

    应该就是说不同标签的数据之间相加或者操作时保持数据可以自动对齐,不乱套。

    labels = pd.Index(np.arange(3))
    labels
    
    • 1
    • 2
    Int64Index([0, 1, 2], dtype='int64')
    
    • 1
    s2 = pd.Series([1.2, -3.2, 0], index=labels)
    s2
    
    • 1
    • 2
    0    1.2
    1   -3.2
    2    0.0
    dtype: float64
    
    • 1
    • 2
    • 3
    • 4
    s2.index is labels
    
    • 1
    True
    
    • 1

    还有一段代码

    df3
    
    • 1
    姓名	小明	   小红	小刚
    课程			
    语文	80.0	90.0	85.0
    数学	85.0	80.0	66.0
    英语	77.0	87.0	69.0
    物理	88.0	NaN	    NaN
    地理	NaN	    80.0	NaN
    化学	NaN	    NaN	    77.0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    df3.columns  
    ## Index(['小明', '小红', '小刚'], dtype='object', name='姓名')
    '小明' in df3.columns
    ## True
    '体育' in df3.index
    ## False
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    这两段代码想要说明什么呢

    返回的都是布尔值。这里反倒有点像python基础部分字典、列表,查看一个元素有没有存在。

    我是不是也可以说查看这个标签有没有存在。

    index类似于集合,但又不是集合,集合里的元素不可以重复,但是index可以

    dup_index = pd.Index(['A','A','B','B'])
    dup_index
    ## Index(['A', 'A', 'B', 'B'], dtype='object')
    
    • 1
    • 2
    • 3

    索引还有一些方法和属性

    方法说明
    append()连接另一个index对象,产生一个新的index
    difference()计算差值,并得到一个index
    intersection()计算交集
    union()计算并集
    `isin()计算一个指标各值是否都包含在参数集合中的布尔型数组
    delete()删除索引处的元素,并得到新的index
    drop()删除传入的值,并得到新的index
    insert()将元素插入索引处,并得到新的index
    is_monotoic()当各元素均大于等于前一个元素时,返回Ture
    is_unique()当index没有重复值时,返回True
    unique()计算index中唯一值的数组
    # 创建两个索引
    idx1 = pd.Index(np.arange(4))
    idx2 = pd.Index(['A','B','C','D'])
    idx3 = pd.Index(['A',2,'C',2])
    
    • 1
    • 2
    • 3
    • 4

    因为是索引的属性,所以,创建三个索引,输出一下

    idx1
    ## Int64Index([0, 1, 2, 3], dtype='int64')
    idx2
    ## Index(['A', 'B', 'C', 'D'], dtype='object')
    idx3
    ## Index(['A', 2, 'C', 2], dtype='object')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    idx1.append(idx2)  # idx1连接idx2 
    ## Index([0, 1, 2, 3, 'A', 'B', 'C', 'D'], dtype='object')
    
    • 1
    • 2

    append()这个方法已经很常见了,就是连接两个序列。

    idx2.difference(idx3) 
    ## Index(['B', 'D'], dtype='object')
    
    • 1
    • 2

    计算差值,就是idx2有而idx3没有的。

    idx3.intersection(idx2)
    ## Index(['A', 'C'], dtype='object')
    
    idx3.union(idx2)
    ## Index([2, 2, 'A', 'B', 'C', 'D'], dtype='object')
    
    • 1
    • 2
    • 3
    • 4
    • 5

    计算交集并集,这个没什么可解释的,

    idx2.delete(2)
    ## Index(['A', 'B', 'D'], dtype='object')
    
    idx3.drop("A")
    ## Index([2, 'C', 2], dtype='object')
    
    • 1
    • 2
    • 3
    • 4
    • 5

    两个都有删除的意思,但是别弄错了,.delete()删除的是元素索引,而drop()删除的是元素

    举个反例康康

    idx2.delete('A')
    ## IndexError: arrays used as indices must be of integer (or boolean) type
    
    idx2.drop(2)
    ## KeyError: '[2] not found in axis
    
    • 1
    • 2
    • 3
    • 4
    • 5

    两种报错不一样。.drop(2)中的2是看成了值来执行,idx2中没有2

    idx3.insert(2,'C')
    ## Index(['A', 2, 'C', 'C', 2], dtype='object')
    
    • 1
    • 2

    在什么地方插入什么,这个要留意!

    idx1.is_monotonic
    ## True
    
    idx2.is_monotonic
    ## True
    
    idx3.is_monotonic
    ## False
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    判断索引是不是递增的,但是根据什么判断呢

    idx2.is_unique
    ## True
    
    idx3.is_unique
    ## False
    
    • 1
    • 2
    • 3
    • 4
    • 5

    判断index里面有没有重复

    idx3.unique(
    ## Index(['A', 2, 'C'], dtype='object')
    
    • 1
    • 2

    让index里的元素全部不充分,所以元素2没有了。

    要注意,上面的所有方法均不改变原index。什么意思呢

    idx3
    ## Index(['A', 2, 'C', 2], dtype='object')
    
    • 1
    • 2

    上面的一切操作并没有改变idx3,所以记得赋值

    idx4 = idx2.drop(2)
    
    • 1

    总结

    这一章太多了,到这里已经写了4500多字了。总结一下

    pandas是什么,是python数据分析的一个重要工具包。

    然后pandas又提出了两种数据类型,Series和DataFrame,一个体现的是一维数据,一个体现的是二维数据,写了4500多字,都是一个对pandas的入门,并没有往深里学。怎么去创建这个数据类型,他们的索引、标签等等概念,然后学了一些相关属性,还可以与numpy进行联动。

    然后学习了索引对象,这个算是非常重要的东西,但也是容易忽略的,我们在处理数据的时候会更有先关注数据,然而忘记索引的存在。

    还是主要牢记这两个数据类型是如何创建的,然后是他们的一些属性。

    好了,我的读书笔记到此结束。

    里面肯定有许许多多的bug,欢迎大家指出!毕竟这样成长更快。

    也感谢大家可以看到这样,如果帮到了你,是我的荣幸。

    谢谢大家!

  • 相关阅读:
    DeFi 对经济模式带来的改变和存在的局限
    gitee码云的使用
    事务隔离级别
    交换机与路由技术-32-命名ACL
    STM32WB55开发(5)----调整射频功率
    漫画:国内都有哪些程序员大牛?
    遗失备份悲剧?迅软DSE来拯救,告诉你不备份的办公文件会带来怎样的下场!
    Unity热更新
    普法Android.mk中的一些宏和Android.bp对应关系
    一文通览腾讯云大数据ES、数据湖计算、云数据仓库产品新版本技术创新
  • 原文地址:https://blog.csdn.net/qq_45348840/article/details/127595210