Pandas 第8章 分类数据

Categoricals 是 pandas 的一种数据类型,对应着被统计的变量。Categoricals 是由固定的且有限数量的变量组成的。比如:性别、社会阶层、血型、国籍、观察时段、赞美程度等等。

与其它被统计的变量相比,categorical 类型的数据可以具有特定的顺序——比如:按程度来设定,“强烈同意”与“同意”,“首次观察”与“二次观察”,但是不能做按数值来进行排序操作(比如:sort_by 之类的,换句话说,categorical 的顺序是创建时手工设定的,是静态的)

类型数据的每一个元素的值要么是预设好的类型中的某一个,要么是空值(np.nan)。顺序是由预设好的类型集合来决定的,而不是按照类型集合中各个元素的字母顺序排序的。categorical 实例的内部是由类型名字集合和一个整数组成的数组构成的,后者标明了类型集合真正的值

摘录于  https://blog.csdn.net/mengenqing/article/details/80616094

以下学习资源来自学习资源

本节主要内容:

目录

category的创建及其性质

分类变量的排序

分类变量的比较操作

问题与练习


 

  1. category的创建及其性质

    1. 分类变量的创建

      1. #1、对于Series数据结构,传入参数dtype='category'即可
            series_cat=pd.Series(["a", "b", "c", "a"], dtype="category")
            series_cat
            
            结果
            0    a
            1    b
            2    c
            3    a
            dtype: category
            Categories (3, object): [a, b, c]
        
            ## series_cat的类型为category,但是没有声明顺序,这时若对Series排序,实际上还是按照词法的顺序:
        
            series_cat.sort_values()
        
            0    a
            3    a
            1    b
            2    c
            dtype: category
            Categories (3, object): [a, b, c]
        
        #2、对DataFrame指定类型创建
            #2、1直接指定类型
        
            temp_df = pd.DataFrame({'A':pd.Series(["a", "b", "c", "a"],          dtype="category"),'B':list('abcd')})
            print(temp_df)
            temp_df.dtypes
        
           结果: 
              A  B
           0  a  a
           1  b  b
           2  c  c
           3  a  d
           A    category
           B      object
           dtype: object
        
           #2、2 也可以在定义数据之后转换类型
            #创建数据框
                df_cat = pd.DataFrame({ 'V1':['A','C','B','D']})
            #转换指定列的数据类型为category
                df_cat['V1'] = df_cat['V1'].astype('category')
                df_cat['V1']
        
        
        # 3、利用内置Categorical类型创建
        
           # pd.Categorical(values, categories=None, ordered=None, dtype=None, fastpath=False)
        
           #3、1 利用pd.Categorical()生成类别型数据后转换为Series,或替换DataFrame中的内容
        
           cat = pd.Categorical(["a", "b", "c", "a"], categories=['a','b','c'])
           pd.Series(cat)
        
           结果:
        
           0    a
           1    b
           2    c
           3    a
           dtype: category
           Categories (3, object): [a, b, c]
        
            #3、2 替换DataFrame中的内容
            categorical_ = pd.Categorical(['A','B','D','C'],
                                      categories=['B','C','D'])
            df_cat = pd.DataFrame({'V1':categorical_})
            df_cat['V1']
               
            结果:
            0    NaN
            1      B
            2      D
            3      C
            Name: V1, dtype: category
            Categories (3, object): [B, C, D]
        
            总结:而pd.Categorical()独立创建categorical数据时有两个新的特性,一是其通过参数    categories定义类别时,若原数据中出现了categories参数中没有的数据,则会自动转换为pd.nan:
        
        #3、3 另外pd.Categorical()还有一个bool型参数ordered,设置为True时则会按照categories中的顺序定义从小到大的范围:
        
             categorical_ = pd.Categorical(['A','B','D','C'],
                                      categories=['A','B','C','D'],
                                     ordered=True)
             df_cat = pd.DataFrame({'V1':categorical_})
             df_cat['V1']
        
        #4、利用pandas.api.types中的CategoricalDtype()对已有数据进行转换
        
            from pandas.api.types import CategoricalDtype
            #创建数据框
            df_cat = pd.DataFrame({'V1':['A','C','B','D']})
            cat = CategoricalDtype(categories=['A','C','B'],ordered=True)
            df_cat['V1'] = df_cat['V1'].astype(cat)
            df_cat['V1']
        
           结果
        
            0      A
            1      C
            2      B
            3    NaN
            Name: V1, dtype: category
            Categories (3, object): [A < C < B]
        
            通过CategoricalDtype(),我们可以结合astype()完成从其他类型数据向categorical数据的转换    过程,利用CategoricalDtype()的参数categories、ordered,弥补.astype('category')的短板(实际    上.astype('category')等价于.astype(CategoricalDtype(categories=None, ordered=False))):
        
        # 5、利用cut函数创建
            pd.cut(x, bins, right:bool=True, labels=None, retbins:bool=False, precision:int=3, 
            include_lowest:bool=False, duplicates:str='raise')
        
        #5、1 默认使用区间类型为标签
              pd.cut(np.random.randint(0,60,5), [0,10,30,60])
        
              out:
                [(30, 60], (0, 10], (30, 60], (30, 60], (30, 60]]
                Categories (3, interval[int64]): [(0, 10] < (10, 30] < (30, 60]]
        
               #可指定字符为标签
                pd.cut(np.random.randint(0,60,5), [0,10,30,60], right=False, labels=['0-10','10-    30','30-60'])
        
         结果:
                    [10-30, 30-60, 30-60, 10-30, 30-60]
                    Categories (3, object): [0-10 < 10-30 < 30-60]
            
        
    2. 分类变量的结构

      1. 一个分类变量包括三个部分,元素值(values)、分类类别(categories)、是否有序(order)

      2. 从上面可以看出,使用cut函数创建的分类变量默认为有序分类变量

      3. 获取属性

        #1、describe方法
        s = pd.Series(pd.Categorical(["a", "b", "c", "a",np.nan], categories=['a','b','c','d']))
        s.describe()
        
        count     4
        unique    3
        top       a
        freq      2
        dtype: object
        
         #2、使用 .cat.categories查看类别名称列表
        
           s= pd.Series([‘a’, ‘b’, ‘c’, ‘c’], dtype=’category’)
        
           s.cat.categories
        
           结果: Index([‘a’, ‘b’, ‘c’], dtype=’object’)
        
          #3、 使用 .cat.ordered 查看类别是否有序
        
             s = pd.Series( pd.Categorical([‘差’, ‘中’, ‘良’, ‘优’], categories=[‘差’, ‘中’, 
            ‘良’, ‘优’], ordered=True))
        
            s.cat.ordered
        
                        outcome: True
        
             a2 = pd.Series([‘a’, ‘b’, ‘c’, ‘c’], dtype=’category’)
        
             a2.cat.ordered
        
                         outcome:False
        
        # 4、读取:cat.categories
        
            a1 = pd.Series([‘a’, ‘b’, ‘c’, ‘c’], dtype=’category’)
        
            a1.cat.categories
        
                outcome:  Index([‘a’, ‘b’, ‘c’], dtype=’object’)
        
            

         

    3. 类别的修改
      #1、修改属性 
      a1 = pd.Series([‘a’, ‘b’, ‘c’, ‘c’], dtype=’category’)
      
          a1.cat.categories
      
              outcome:  Index([‘a’, ‘b’, ‘c’], dtype=’object’)
      
       a1.cat.categories=[‘类别a’, ‘类别b’, ‘c’]
      
          a1
      
      outcome:    0 类别a
      
                          1    类别b
      
                          2      c
      
                          3      c
      
                          dtype: category
      
                          Categories (3, object): [类别a, 类别b, c]
      
      #2、利用set_categories修改
          s = pd.Series(pd.Categorical(["a", "b", "c", "a",np.nan], categories=   ['a','b','c','d']))
          print(s)
          s.cat.set_categories(['new_a','c'])
      
      outcome:
      0      a
      1      b
      2      c
      3      a
      4    NaN
      dtype: category
      Categories (4, object): [a, b, c, d]
      0    NaN
      1    NaN
      2      c
      3    NaN
      4    NaN
      dtype: category
      Categories (2, object): [new_a, c]
      
      #3、利用rename_categories修改, 需要注意的是该方法会把值和分类同时修改
      
          s = pd.Series(pd.Categorical(["a", "b", "c", "a",np.nan], categories=    ['a','b','c','d']))
      print(s)
      s.cat.rename_categories(['new_%s'%i for i in s.cat.categories])
      
      outcome;
      0      a
      1      b
      2      c
      3      a
      4    NaN
      dtype: category
      Categories (4, object): [a, b, c, d]
      0    new_a
      1    new_b
      2    new_c
      3    new_a
      4      NaN
      dtype: category
      Categories (4, object): [new_a, new_b, new_c, new_d]
      
      5、利用字典修改,也会把值和类型都改变
      s.cat.rename_categories({'a':'new_a','b':'new_b'})
      
      outcome
      0    new_a
      1    new_b
      2        c
      3    new_a
      4      NaN
      dtype: category
      Categories (4, object): [new_a, new_b, c, d]
      
      
      # 6、利用add_categories添加
          s = pd.Series(pd.Categorical(["a", "b", "c", "a",np.nan], categories=['a','b','c','d']))
      s.cat.add_categories(['e'])
      
      outcome:
      0      a
      1      b
      2      c
      3      a
      4    NaN
      dtype: category
      Categories (5, object): [a, b, c, d, e]
      
      # 7、利用remove_categories移除
      s = pd.Series(pd.Categorical(["a", "b", "c", "a",np.nan], categories=['a','b','c','d']))
      s.cat.remove_categories(['d'])
      
      # 8、 删除元素值未出现的分类类型
          s = pd.Series(pd.Categorical(["a", "b", "c", "a",np.nan], categories=['a','b','c','d']))
      s.cat.remove_unused_categories()
      
      outcome;
      0      a
      1      b
      2      c
      3      a
      4    NaN
      dtype: category
      Categories (3, object): [a, b, c]

       

  2. 分类变量的排序
    1. # 无序变为有序
          1、.cat.as_ordered方法
              s = pd.Series(["a", "d", "c", "a"]).astype('category').cat.as_ordered()
              s
      
         OUTCOME 
          0    a
          1    d
          2    c
          3    a
          dtype: category
          Categories (3, object): [a < c < d]
      2、有序变为无序.cat.as_unordered()
      
          s.cat.as_unordered()
      3、利用.cat.set_categories方法中的order参数
          pd.Series(["a", "d", "c",     "a"]).astype('category')
          .cat.set_categories(['a','c','d'],ordered=True)
      4。利用.cat.reorder_categories方法,这个方法的特点在于,新设置的分类必须与原分类为同一集合
          s = pd.Series(["a", "d", "c", "a"]).astype('category')
          s.cat.reorder_categories(['a','c','d'],ordered=True)
      
      5、值排序和索引排序都是适用的
          

       

  3. 分类变量的比较操作
    1. 与标量数据或等长序列的比较:
      1. 两个分类变量的等式判别需要满足分类完全相同

    2. 与另外一个分类变量比较
      1.  
  4. 问题与练习

1.4.0.1  【问题一】 如何使用union_categoricals方法?它的作用是什么?

1、
from pandas.api.types import union_categoricals
a = pd.Categorical(["b", "c"])
b = pd.Categorical(["a", "b"])
union_categoricals([a, b])
#对分类数据求集合,下面会报错

a = pd.Categorical(["a", "b"], ordered=True)
b = pd.Categorical(["a", "b", "c"], ordered=True)
union_categoricals([a, b])

TypeError :to union ordered Categoricals, all categories must be the same

1.4.0.2  【问题二】 利用concat方法将两个序列纵向拼接,它的结果一定是分类变量吗?什么情况下不是?

1.4.0.3  【问题三】 当使用groupby方法或者value_counts方法时,分类变量的统计结果和普通变量有什么区别?

1.4.0.4  【问题四】 下面的代码说明了Series创建分类变量的什么“缺陷”?如何避免?(提示:使用Series中的copy参数)

【练习一】 现继续使用第四章中的地震数据集,请解决以下问题:

1.4.0.6  (a)现在将深度分为七个等级:[0,5,10,15,20,30,50,np.inf],请以深度等级Ⅰ,Ⅱ,Ⅲ,Ⅳ,Ⅴ,Ⅵ,Ⅶ为索引并按照由浅到深的顺序进行排序。

d=pd.read_csv('data/Earthquake.csv').head()
pd.cut(d['深度'], [0,5,10,15,20,30,50,np.inf],labels=['Ⅰ','Ⅱ','Ⅲ','Ⅳ','Ⅴ','Ⅵ','Ⅶ'])
d.set_index('深度').sort_index().head()

1.4.0.7  (b)在(a)的基础上,将烈度分为4个等级:[0,3,4,5,np.inf],依次对南部地区的深度和烈度等级建立多级索引排序。

方向里边没有南部啊??????

d['烈度'] = pd.cut(d['烈度'], [0,3,4,5,np.inf],labels=['Ⅰ','Ⅱ','Ⅲ','Ⅳ'])
d.set_index(['深度','烈度']).sort_index().head()

【练习二】 对于分类变量而言,调用第4章中的变形函数会出现一个BUG(目前的版本下还未修复):例如对于crosstab函数,按照官方文档的说法,即使没有出现的变量也会在变形后的汇总结果中出现,但事实上并不是这样,比如下面的例子就缺少了原本应该出现的行'c'和列'f'。基于这一问题,请尝试设计my_crosstab函数,在功能上能够返回正确的结果。

参考答案:

def my_crosstab(foo,bar):
    num = len(foo)
    s1 = pd.Series([i for i in list(foo.categories.union(set(foo)))],name='1nd var')
    s2 = [i for i in list(bar.categories.union(set(bar)))]
    df = pd.DataFrame({i:[0]*len(s1) for i in s2},index=s1)
    for i in range(num):
        df.at[foo[i],bar[i]] += 1
    return df.rename_axis('2st var',axis=1)
my_crosstab(foo,bar)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章