Pandas层次化索引与数据读取

讨论 小哲
Lv1 居士
发布在 Pandas   2503   0
讨论 小哲   2503   0

    5.层次化索引

    5.1 认识层次化索引

    在一个轴方向上有多层索引。如图:

    undefined

    Series和DataFrame均可以实现层次化索引,最常见的方式是在构造方法的index参数中传入一个嵌套列表。

    5.1.1 Series对象层次化索引

    例如:

    import pandas as pd
    mulitindex_series = pd.Series(
        [12462, 1546, 1234, 123, 5456, 5554, 33213, 2124],
        index=[['河北省', '河北省', '河北省', '河北省', '河南省', '河南省', '河南省', '河南省'],
               ['石家庄市', '唐山市', '邯郸市', '秦皇岛市', '郑州市', '开封市', '洛阳市', '新乡市']])
    print(mulitindex_series)

    输出为:

    河北省  石家庄市    12462
         唐山市      1546
         邯郸市      1234
         秦皇岛市      123
    河南省  郑州市      5456
         开封市      5554
         洛阳市     33213
         新乡市      2124
    dtype: int64
    5.1.2 DataFrame对象层次化索引

    例如:

    import pandas as pd
    mulitindex_DataFrame = pd.DataFrame(
        {'占地面积': [12462, 1546, 1234, 123, 5456, 5554, 33213, 2124]},
        index=[['河北省', '河北省', '河北省', '河北省', '河南省', '河南省', '河南省', '河南省'],
               ['石家庄市', '唐山市', '邯郸市', '秦皇岛市', '郑州市', '开封市', '洛阳市', '新乡市']])
    print(mulitindex_DataFrame)

    输出:

               占地面积
    河北省 石家庄市  12462
        唐山市    1546
        邯郸市    1234
        秦皇岛市    123
    河南省 郑州市    5456
        开封市    5554
        洛阳市   33213
        新乡市    2124

    5.2 常用方法

    层次化索引除了直接创建之外还可以通过MultiIndex类的方法构建层次化索引,这个类提供了三种创建层次化索引的方法:

    • MultiIndex.from_tuples():将元组列表转换为MultiIndex
    • MultiIndex.from_arrays():将数组列表转换为MultiIndex
    • MultiIndex.from_product():从多个集合的笛卡尔乘积中创建MultiIndex

    from_tuples()方法可以将包含若干个元组的列表转换为MultiIndex对象,其中元组的第一个元素作为外层索引,第二个元素作为内层索引,例如:

    import pandas as pd
    from pandas import MultiIndex
    list_tuples = [('A', 'A1'), ('A', 'A2'), ('B', 'B1'), ('B', 'B2'), ('B', 'B3')]
    multi_index = MultiIndex.from_tuples(tuples=list_tuples,
                                          names=['外层索引', '内层索引'])
    value = [[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15]]
    df_indexs = pd.DataFrame(data=value,index=multi_index)
    print(df_indexs)

    输出为:

                0   1   2
    外层索引 内层索引
    A    A1     1   2   3
         A2     4   5   6
    B    B1     7   8   9
         B2    10  11  12
         B3    13  14  15

    from_arrays()方法是将数组列表转换为MultiIndex对象,其中嵌套的第一个列表将作为外层索引,嵌套的第二个列表将作为内层索引。例如:

    import pandas as pd
    from pandas import MultiIndex
    multi_array = MultiIndex.from_arrays(
        arrays=[['A', 'A', 'B', 'B', 'B'], ['A1', 'A2', 'B1', 'B2', 'B3']])
    value = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15]]
    df_indexs = pd.DataFrame(data=value, index=multi_array)
    print(df_indexs)

    输出:

           0   1   2
    A A1   1   2   3
      A2   4   5   6
    B B1   7   8   9
      B2  10  11  12
      B3  13  14  15

    from_product()方法表示从多个集合的笛卡尔乘积创建一个MultiIndex对象。

    什么是笛卡尔乘积? 笛卡尔积的符号化为: A×B={(x,y)|x∈A∧y∈B} 例如,A={a,b}, B={0,1,2},则 A×B={(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)} B×A={(0, a), (0, b), (1, a), (1, b), (2, a), (2, b)}

    例如:

    import numpy as np
    import pandas as pd
    from pandas import MultiIndex
    numbers = [0, 1, 2]
    colors = ['green', 'purple']
    multi_product = MultiIndex.from_product(iterables=[numbers, colors],
                                            names=['number', 'color'])
    value = np.array([[7, 5], [6, 6], [3, 1], [5, 5], [4, 5], [5, 3]])
    df_product = pd.DataFrame(data=value, index=multi_product)
    print(df_product)

    输出为:

                   0  1
    number color
    0      green   7  5
           purple  6  6
    1      green   3  1
           purple  5  5
    2      green   4  5
           purple  5  3

    5.3 层次化索引操作

    任务一:录入下面层次化对象

    undefined

    代码:

    import pandas as pd
    ser_obj = pd.Series([78, 65, 44, 98, 66, 100, 97, 68],
                        index=[['机械', '机械', '机械', '信息', '信息', '工程', '工程', '工程'],
                               ['张三', '李四', '王二', '宋天', '汪全', '寒月', '天使', '葛藤']])

    输出:

    机械  张三     78
        李四     65
        王二     44
    信息  宋天     98
        汪全     66
    工程  寒月    100
        天使     97
        葛藤     68
    dtype: int64
    任务二:筛选外层索引为机械的数据

    代码:

    print(ser_obj['机械'])

    输出:

    张三    78
    李四    65
    王二    44
    dtype: int64
    任务三:筛选内层索引为李四的数据

    代码:

    print(ser_obj[:, '李四'])

    输出:

    机械    65
    dtype: int64
    任务四:交换分层顺序

    代码:

    print(ser_obj.swaplevel())

    输出:

    张三  机械     78
    李四  机械     65
    王二  机械     44
    宋天  信息     98
    汪全  信息     66
    寒月  工程    100
    天使  工程     97
    葛藤  工程     68
    dtype: int64
    任务五:索引排序

    sort_index()语法

    sort_index(axis=0,level=None,ascending=True,inplace=False,kind='quicksort',na_position='last',sort_remaining=True,by=None)
    • by:表示按指定的值排序
    • ascending:布尔值,表示是否升序排列,默认为True

    代码:

    print(ser_obj.sort_index())

    输出:

    信息  宋天     98
        汪全     66
    工程  天使     97
        寒月    100
        葛藤     68
    机械  张三     78
        李四     65
        王二     44
    dtype: int64

    层次化索引中先对外层索引进行排序再对每一个外层索引的内层索引进行排序。如果需要对值进行排序可以使用sort_values()函数。

    任务六:录入下面的层次化对象并对num列进行降序排序

    undefined

    代码:

    import pandas as pd
    dat_obj = pd.DataFrame(
        {
            "model": [
                'CPU', 'GPU', 'FLASH', 'SSD', 'HDD', 'USB', 'TYPE-C', 'MIC-USB',
                'DRIVE'
            ],
            "num": [80, 152, 113, 354, 1, 231, 35, 12, 7]
        },
        index=[['A', 'A', 'A', 'B', 'B', 'C', 'C', 'C', 'C'],
               [1, 2, 4, 3, 5, 1, 5, 8, 1]])
    print(dat_obj.sort_values(by='num', ascending=False))

    输出:

           model  num
    B 3      SSD  354
    C 1      USB  231
    A 2      GPU  152
      4    FLASH  113
      1      CPU   80
    C 5   TYPE-C   35
      8  MIC-USB   12
      1    DRIVE    7
    B 5      HDD    1

    6. 数据的读写

    6.1 读写文本文件

    6.1.1 写入文本文件函数to_csv()
    函数语法:

    详细参数请查看官方文档:DataFrame.to_csv()

    to_csv(path_or_buf=None,sep=',',na_rep='',float_format=None,columns=None,header=True,index=True,index_label=None,mode='w',……)
    • path_or_buf:文件路径
    • index:默认为True,若设为False,则将不会显示索引
    • sep:分隔符,默认用","隔开
    代码:
    import pandas as pd
    data_csv = pd.DataFrame(
        {
            "model": [
                'CPU', 'GPU', 'FLASH', 'SSD', 'HDD', 'USB', 'TYPE-C', 'MIC-USB',
                'DRIVE'
            ],
            "num": [80, 152, 113, 354, 1, 231, 35, 12, 7]
        },
        index=[['A', 'A', 'A', 'B', 'B', 'C', 'C', 'C', 'C'],
               [1, 2, 4, 3, 5, 1, 5, 8, 1]])
    data_csv.to_csv('./test.csv', index=True)

    这种方法同样可以输出扩展名为txt的文件。

    输出:

    在本目录会生成一个text.csv的文件,文件内容为:

    ,,model,num
    A,1,CPU,80
    A,2,GPU,152
    A,4,FLASH,113
    B,3,SSD,354
    B,5,HDD,1
    C,1,USB,231
    C,5,TYPE-C,35
    C,8,MIC-USB,12
    C,1,DRIVE,7
    6.1.2 读取文本文件函数read_csv()
    函数语法:

    详细参数请查看官方文档:Pandas.read_csv()

    Pandas.read_csv(filepath_or_buffer,sep=',',delimiter=None,header='infer',names=None,index_col=None,usecols=None,prefix=None,……)
    • sep:指定使用的分隔符,默认用","分隔
    • header:指定行数用来作为列名
    • names:用于结果的列名列表,如果文件不包含标题行,则应该将参数设置为None

    读取Text文件函数read_table()read_csv()相似,只不过read_table()函数默认使用"\t"为分隔符。

    代码:

    读取上文中生成的test.csv文件

    import pandas as pd
    data = pd.read_csv('./test.csv')
    print(data)
    输出:
      Unnamed: 0  Unnamed: 1    model  num
    0          A           1      CPU   80      
    1          A           2      GPU  152      
    2          A           4    FLASH  113      
    3          B           3      SSD  354      
    4          B           5      HDD    1      
    5          C           1      USB  231      
    6          C           5   TYPE-C   35      
    7          C           8  MIC-USB   12      
    8          C           1    DRIVE    7

    可以通过del data['Unnamed: 0']来删除该列。

    6.2 读写EXCEL文件

    excel文件是常见的存储数据文件,它里面均是以二维表格的形式显示的,可以对数据进行统计分析等操作,常见扩展名为.xls.xlsx两种格式,对于excel文件的读写常用的两个方法为to_excel()read_excel()两种方法。

    6.2.2 写入excel文件to_excel()方法
    函数语法:

    详细参数请查看官方文档:DataFrame.to_excel()

    DataFrame.to_excel(excel_writer,sheet_name='Sheet1',na_rep='',float_format=None,columns=None,header=True,index=True,……)
    • excel_writer:表示读取的文件路径
    • sheet_name:表示工作表名称,默认为Sheet1
    • na_rep:表示缺失数据
    • index:表示是否写行索引,默认为True
    代码:

    读取上文中生成的test.csv文件

    import pandas as pd
    data_excel = pd.DataFrame(
        {
            "model": [
                'CPU', 'GPU', 'FLASH', 'SSD', 'HDD', 'USB', 'TYPE-C', 'MIC-USB',
                'DRIVE'
            ],
            "num": [80, 152, 113, 354, 1, 231, 35, 12, 7]
        },
        index=[['A', 'A', 'A', 'B', 'B', 'C', 'C', 'C', 'C'],
               [1, 2, 4, 3, 5, 1, 5, 8, 1]])
    data_excel.to_excel('./test.xlsx', 'Testexcel')
    输出:

    将在根目录输出文件名为test.xlsx的表格,表格内容如图。

    undefined

    6.2.2 读取excel文件read_excel()方法

    注意:有关Excel的操作在Python 3.8下可能会报错,建议使用Python 3.7

    函数语法:

    详细参数请查看官方文档:Pandas.read_excel()

    Pandas.read_excel(io,sheet_name=0,header=0,name=None,index_col=None,**kwds)
    • io:表示路径对象
    • sheet_name:指定要读取的工作表,默认为0
    • header:用于解析DataFrame的列标签,默认为0,即取第一列为列标题
    • index_col:用于解析DataFrame的行标签,默认为None,如果表格中第一列为索引则将该属性设置为0
    • names:要使用的列名称
    代码:

    读取上文中生成的test.xlsx文件,由于excel中合并的单元格会产生缺失值,使用ffill()方法进行向下填充。

    import pandas as pd
    data = pd.read_excel('./test.xlsx').ffill()
    print(data)
    输出:
      Unnamed: 0  Unnamed: 1    model  num
    0          A           1      CPU   80
    1          A           2      GPU  152
    2          A           4    FLASH  113
    3          B           3      SSD  354
    4          B           5      HDD    1
    5          C           1      USB  231
    6          C           5   TYPE-C   35
    7          C           8  MIC-USB   12
    8          C           1    DRIVE    7

    6.3 读写HTML文件

    6.3.1 读取HTML表格方法read_html()方法
    函数语法:

    详细参数请查看官方文档:pandas.read_html()

    Pandas.read_html(io,match='.+',flavor=None,header=None,index_col=None,skiprows=None,attrs=None)
    • io:表示路径对象
    • header:表示指定列标题所在的行
    • index_col:表示指定行标题对应的列
    • attrs:默认为None,用于表示表格的属性值
    代码:

    将使用read_html()方法读取http://gaokao.xdf.cn/201805/10781393.html的表格:

    undefined

    import requests
    import pandas as pd
    html_data = requests.get('http://gaokao.xdf.cn/201805/10781393.html')
    html_read = pd.read_html(html_data.content, encoding='utf-8')
    print(html_read[0])
    输出:
         0           1   2     3
    0   排名        学校名称  省市    总分
    1    1        清华大学  北京  95.3
    2    2        北京大学  北京  78.6
    3    3        浙江大学  浙江  73.9
    4    4      上海交通大学  上海  73.1
    ..  ..         ...  ..   ...
    95  94      中国政法大学  北京  37.6
    96  96      大连医科大学  辽宁  37.5
    97  97  中国石油大学(北京)  北京  37.3
    98  98        西北大学  陕西  37.2
    99  98      中国传媒大学  北京  37.2
    
    [100 rows x 4 columns]
    6.3.2 写入HTML表格方法to_html()方法
    函数语法:

    详细参数请查看官方文档:DataFrame.to_html()

    DataFrame.to_html(buf,index,header)
    • buf:输出路径
    • index:行索引,默认为True
    • header:列索引,默认为True
    代码:

    将上文读取到的表格的前十名写入到test.html中,不保留行列索引:

    html_read[0][:11].to_html('./test.html', index=False, header=False)
    输出:

    undefined

    6.4 读写sql文件

    Padnas支持Mysql、Oracle、SQLite等主流数据库的读写操作,为了高效读取数据库中的数据,需要引入SQLAlchemy软件,引入之后Pandas的io.sql模块将读写数据库,其中提供的常用函数如下表所示:

    函数名称 说明
    read_sql_table() 将读取的整张数据表中的数据转化成DataFrame对象
    read_sql_query() 将sql语句读取的结果转换成DataFrame对象
    read_sql() 上述两个函数的结合,既可以读数据表也可读SQL语句
    to_sql() 将数据写入到SQL数据库中

    本文将使用mysql数据库,Python需要使用:

    pip install mysql-connector-python

    如果使用的是Conda则需要使用:

    conda install mysql-connector-python

    安装模块。

    6.4.1 写入数据库函数to_sql()
    函数语法:

    详细参数请查看官方文档:DataFrame.to_sql() Series.to_sql()

    to_sql(name,con,schema=None,if_exists='fail',index=True,index_label=None,chunksize=None,dtype=None)
    • name:表示数据库表的名称
    • con:接收数据库连接信息
    • if_exists:可以取值为fail,replace,append等,默认为fail

    在对数据库进行写入前需要首先创建数据库,使用mysql终端输入:

    create database test;

    创建test数据库。更多数据库指令参照:Sql教程 MySQL 教程

    代码:

    创建一个DataFrame对象并将其写入test数据库中的students表。

    from sqlalchemy import create_engine
    import pandas as pd
    df = pd.DataFrame({
        "班级": ["一年级", "二年级", "三年级", "四年级"],
        "男生人数": [25, 23, 27, 30],
        "女生人数": [19, 17, 20, 20]
    })
    engine = create_engine("mysql+mysqlconnector://root:root@127.0.0.1:3306/test")
    df.to_sql('students',engine)
    输出:

    通过在Mysql数据库中输入:

    use test; /*使用test数据库*/
    show tables; /*显示数据库中的数据表*/
    select *from students; /*输出students数据表*/

    undefined

    至此,表格已经创建成功了。

    6.4.1 读取数据表函数read_sql()
    函数语法:

    详细参数请查看官方文档:pandas.read_sql()

    pandas.read_sql(sql,con,index_col=None,coerce_float=True,params=None,parse_dates=None,columns=None,chunksize=None)
    • sql:表示被执行的SQL语句
    • con:接收数据库连接,表示数据库的连接信息
    • columns:从SQL表中选择列名列表

    注意:通过create_engine()函数创建连接时,需要指定格式如下:'数据库类型+数据库驱动名称//用户名:密码@机器地址:端口号/数据库名'

    代码:

    读取上文中test/students数据表中的内容并写入名称为data_sqlDataFrame对象中。

    from sqlalchemy import create_engine
    import pandas as pd
    engine = create_engine(
        "mysql+mysqlconnector://root:root@127.0.0.1:3306/test")
    sql = "select *from students"
    data_sql = pd.read_sql(sql, engine)
    print(data_sql)
    输出:
       index   班级  男生人数  女生人数
    0      0  一年级    25    19
    1      1  二年级    23    17
    2      2  三年级    27    20
    3      3  四年级    30    20
    版权声明:作者保留权利,不代表意本站立场。如需转载请联系本站以及作者。

    参与讨论

    回复《 Pandas层次化索引与数据读取

    EditorJs 编辑器

    沙发,很寂寞~
    反馈
    to-top--btn