• Pandas的Categorical Data


    http://liao.cpython.org/pandas15/

    • Docs »
    • Pandas的Categorical Data类型

    15. Pandas的Categorical Data

    pandas从0.15版开始提供分类数据类型,用于表示统计学里有限且唯一性数据集,例如描述个人信息的性别一般就男和女两个数据常用'm'和'f'来描述,有时也能对应编码映射为0和1。血型A、B、O和AB型等选择可以映射为0、1、2、3这四个数字分别代表各个血型。pandas里直接就有categorical类型,可以有效地对数据进行分组进行相应的汇总统计工作。

    当DataFrame的某列(字段)上的数据值是都是某有限个数值的集合里的值的时候,例如:性别就男和女,有限且唯一。这列可以采用Categorical Data类型来存储、统计。

    pandas的Categorical Data类型灵感来源于Data wareHorsing数据仓库里的维度表设计理念,即某列数据存储的不是数据本身,而是该数据对应的编码(有称为分类、字典编码) 这些编码比数据本身存储依赖的空间小,但能基于编码统计汇总的速度要比数据本身的存储、统计速度要快。

    15.1 如何理解Categorical Data?

    下面看一张某水果超市的供货商表(表1):

    供货商水果价格
    1 apple 5.20
    2 pearl 3.50
    3 orange 7.30
    5 apple 5.00
    6 orange 7.50
    7 orange 7.30
    9 apple 5.20
    4 pearl 3.70
    8 orange 7.30

    第2列是各个水果供应商的能供应的水果类型,目前市场也就apple、pearl、orange三种水果可以买到,对于一个大超市而言可能这个表很长、有很多的水果供应商,假设有1亿条数据,那么数据存储所需空间主要浪费在水果名字上了,其他字段都是数值型的数据,而水果这一列是字符串型的,很占空间,如何能降低这张大表的存储空间浪费呢? 设计一个辅助的水果编码表(表2):

    编码水果
    0 apple
    1 pearl
    2 orange

    那么供应商的表就变为(表3):

    供货商水果价格
    1 0 5.20
    2 1 3.50
    3 2 7.30
    5 0 5.00
    6 2 7.50
    7 2 7.30
    9 0 5.20
    4 1 3.70
    8 2 7.30

    变化后的表的数据存储所需的空间量就下来了。也就是说在供应商表里存储的不是水果名数据本身而是存储的水果对应的编码值(通常用整形数据)。可以查供应商表里水果的编码再查辅助的编码表找到水果名。这个水果的编码表在数据仓库里称为维度表(dimension tables)。 而pandas的categorical data的作用就是构建并依赖这个维度表,即例子里的水果编码表。pandas里维度表里记录着若干且唯一的几个分类,可以通过categorical数据的categories 属性获得而数据的所一一对应的编码可以通过codes获得。

    编码水果
    0 apple
    1 pearl
    2 orange

    当DataFrame里的某列数据采用categorical Data方式,那么这列数据的存储会大大降低。

    import pandas as pd
    import time
    
    idx = [1,2,3,5,6,7,9,4,8]
    name = ["apple","pearl","orange", "apple","orange","orange","apple","pearl","orange"]
    price = [5.20,3.50,7.30,5.00,7.50,7.30,5.20,3.70,7.30]
    df = pd.DataFrame({ "fruit": name , "price" : price}, index = idx)
    print df,"
    "
    print df.memory_usage(),"
    "
    print df.dtypes
    print "*" * 20
    df['fruit'] = df['fruit'].astype('category')
    print df
    print df.memory_usage(),"
    "
    print df.dtypes
    

    程序的执行结果:

        fruit  price
    1   apple    5.2
    2   pearl    3.5
    3  orange    7.3
    5   apple    5.0
    6  orange    7.5
    7  orange    7.3
    9   apple    5.2
    4   pearl    3.7
    8  orange    7.3 
    
    fruit    72
    price    72
    dtype: int64 
    
    fruit     object
    price    float64
    dtype: object
    ********************
        fruit  price
    1   apple    5.2
    2   pearl    3.5
    3  orange    7.3
    5   apple    5.0
    6  orange    7.5
    7  orange    7.3
    9   apple    5.2
    4   pearl    3.7
    8  orange    7.3
    fruit    33
    price    72
    dtype: int64 
    
    fruit    category
    price     float64
    dtype: object
    

    最初创建的DataFrame变量df的各个列的类型:

    fruit     object
    price    float64
    dtype: object
    

    经语句df['fruit'] = df['fruit'].astype('category')将fruit列由Series改为了category类型。

    fruit    category
    price     float64
    dtype: object
    

    请注意fruit列的类型的变化。正是因为fruit采用了category类型,其存储所需的空间由之前的

    fruit    72
    price    72
    dtype: int64 
    

    变为

    fruit    33
    price    72
    dtype: int64 
    

    即72变为33,变化了,尽管原始的DataFrame数据量不大,所以变化比率也不大。读者可以适当加大df的数据长度,可以看到很明显的存储容量的降低。

    import pandas as pd
    import time
    
    idx = [1,2,3,5,6,7,9,4,8]
    name = ["apple","pearl","orange", "apple","orange","orange","apple","pearl","orange"]
    price = [5.20,3.50,7.30,5.00,7.50,7.30,5.20,3.70,7.30]
    #df = pd.DataFrame({ "fruit": name , "price" : price}, index = idx)
    N = 100000
    df = pd.DataFrame({ "fruit": name * N, "price" : price * N}, index = idx * N)
    print df[:4]
    print df.memory_usage(),"
    "
    print df.dtypes
    print "*" * 20
    df['fruit'] = df['fruit'].astype('category')
    print df[:4]
    print df.memory_usage(),"
    "
    print df.dtypes
    

    执行结果:

        fruit  price
    1   apple    5.2
    2   pearl    3.5
    3  orange    7.3
    5   apple    5.0 
    
    fruit    7200000
    price    7200000
    dtype: int64 
    
    fruit     object
    price    float64
    dtype: object
    ********************
        fruit  price
    1   apple    5.2
    2   pearl    3.5
    3  orange    7.3
    5   apple    5.0
    fruit     900024
    price    7200000
    dtype: int64 
    
    fruit    category
    price     float64
    dtype: object
    

    15.2 理解category

    总结一下pandas的category数据,两次打印DataFrame数据df的结果都是一样的,但是第二次打印的df是其fruit列经语句df['fruit'] = df['fruit'].astype('category')改变了其数据类型已不是Series而是category类型,该列存储所需的内存使用容量大大降低。

    import pandas as pd
    import time
    
    idx = [1,2,3,5,6,7,9,4,8]
    name = ["apple","pearl","orange", "apple","orange","orange","apple","pearl","orange"]
    price = [5.20,3.50,7.30,5.00,7.50,7.30,5.20,3.70,7.30]
    #df = pd.DataFrame({ "fruit": name , "price" : price}, index = idx)
    N = 1
    df = pd.DataFrame({ "fruit": name * N, "price" : price * N}, index = idx * N)
    df['fruit'] = df['fruit'].astype('category')
    print df,"
    "
    print "df.price.values
    ", df.price.values,"
    "
    print "df.fruit.values
    ", df.fruit.values, "
    "
    print "df.fruit.values.codes
    ",df.fruit.values.codes, "
    "
    print "df.fruit.values.categories
    ",df.fruit.values.categories, "
    "
    

    fruit列是category类型的,通过codes和categorie组合出fruit的values。

        fruit  price
    1   apple    5.2
    2   pearl    3.5
    3  orange    7.3
    5   apple    5.0
    6  orange    7.5
    7  orange    7.3
    9   apple    5.2
    4   pearl    3.7
    8  orange    7.3 
    
    df.price.values
    [5.2 3.5 7.3 5.  7.5 7.3 5.2 3.7 7.3] 
    
    df.fruit.values
    [apple, pearl, orange, apple, orange, orange, apple, pearl, orange]
    Categories (3, object): [apple, orange, pearl] 
    
    df.fruit.values.codes
    [0 2 1 0 1 1 0 2 1] 
    
    df.fruit.values.categories
    Index([u'apple', u'orange', u'pearl'], dtype='object') 
    

    values对应于表1里的第2列即显示输出时“水果”,codes对应于表3的第2列即存储时“水果”列,categories对应于表2的“水果”列即有限唯一的一个集合。

    15.3 总结

    Categorical Data数据由codes和categories组成,categories是有限且唯一的分类集合,codes是原数据对应的分类的编码, Categorical Data不要求有限并唯一。

  • 相关阅读:
    Linux下使用curl查看http请求各阶段耗时
    yum list查看版本
    【k8s】XX 修改ipvs模式
    域名访问时间 测试脚本
    关闭WINDOWS自动检测互联网络
    win10专业版安装VMware workstation pro 16时提示“setup failed to generate the ssl keys necessary to run vmware”笔记
    手动启动MegaRAID Storage Manager v17.05.02.01 for Linux
    Java基于POI实现excel任意多级联动下拉列表——支持从数据库查询出多级数据后直接生成【附源码】
    C# 后台POST数据及API接收简记
    Linux 安装pycharm,清除缓存,scp传输文件
  • 原文地址:https://www.cnblogs.com/lvdongjie/p/11327044.html
Copyright © 2020-2023  润新知