pandas学习笔记(九)

pandas学习笔记(九)

一、cat对象

1.cat对象的属性

pandas 中提供了 category 类型,使用户能够处理分类类型的变量,将一个普通序列转换成分类变量可以使用 astype 方法:

df = pd.read_csv('./learn_pandas.csv',
  ...:      usecols = ['Grade','Name','Gender','Height','Weight'])
s = df.Grade.astype('category')
s.head()
Out[5]: 
0     Freshman
1     Freshman
2       Senior
3    Sophomore
4    Sophomore
Name: Grade, dtype: category
Categories (4, object): ['Freshman', 'Junior', 'Senior', 'Sophomore']

对于一个具体的分类,有两个组成部分

  • 其一为类别的本身,它以Index类型储存

  • 其二为是否有序,它们都可以通过cat的属性被访问

    s.cat.categories
    Out[7]: Index(['Freshman', 'Junior', 'Senior', 'Sophomore'], dtype='object')
    s.cat.ordered
    Out[8]: False
    

每一个序列的类别会被赋予唯一的整数编号,它们的编号取决于 cat.categories 中的顺序,该属性可以通过 codes 访问:

s.cat.codes.head()
Out[9]: 
0    0
1    0
2    2
3    3
4    3
dtype: int8
2.类别的增加、删除和修改

通过 cat 对象的 categories 属性能够完成对类别的查询,那么应该如何进行“增改查删”的其他三个操作呢?

  • 对于类别的增加可以使用add_categories

    s = s.cat.add_categories('Graduate') # 增加一个毕业生类别
    s.cat.categories
    Out[11]: Index(['Freshman', 'Junior', 'Senior', 'Sophomore', 'Graduate'], dtype='object')
    
  • 删除某一个类别可以使用remove_categories同时所有原来序列中的该类会被设置为缺失

    s = s.cat.remove_categories('Freshman') # 删除大一类别
    s.cat.categories
    Out[13]: Index(['Junior', 'Senior', 'Sophomore', 'Graduate'], dtype='object')
    s.head()
    Out[14]: 
    0          NaN
    1          NaN
    2       Senior
    3    Sophomore
    4    Sophomore
    Name: Grade, dtype: category
    Categories (4, object): ['Junior', 'Senior', 'Sophomore', 'Graduate']
    
  • 可以使用set_categories直接设置序列的新类别,原来的类别中如果存在元素不属于新类别,那么会被设置为缺失

    s = s.cat.set_categories(['Sophomore','PhD']) # 新类别为大二学生和博士
    s.cat.categories
    Out[18]: Index(['Sophomore', 'PhD'], dtype='object')
    s.head()
    Out[19]: 
    0          NaN
    1          NaN
    2          NaN
    3    Sophomore
    4    Sophomore
    Name: Grade, dtype: category
    Categories (2, object): ['Sophomore', 'PhD']
    
  • 可以用rmove_unused_categories删除未出现在序列中的类别:

    s = s.cat.remove_unused_categories() # 删除了未出现过的博士类别
    s.cat.categories
    Out[20]: Index(['Sophomore'], dtype='object')
    
  • rename_categories可以使用来对类别名进行修改同时需要注意的是,这个方法会对原序列的对应值也进行相应修改

    s = s.cat.rename_categories({'Sophomore':'本科二年级学生'})
    s.head()
    Out[22]: 
    0        NaN
    1        NaN
    2        NaN
    3    本科二年级学生
    4    本科二年级学生
    Name: Grade, dtype: category
    Categories (1, object): ['本科二年级学生']
    

二、有序分类

1.序的建立

有序类别和无序类别之间的相互转化

  • as_unordered

  • reorder_categories,传入的参数必须是由当前序列的无需类别构成的列表,不能够增加新的类别,也不能缺少原来的类别,并且必须指定参数 ordered=True ,否则方法无效

    # 例如,对年级高低进行相对大小的类别划分,然后再恢复无序状态:
    
    s = df.Grade.astype('category')
    s = s.cat.reorder_categories(['Freshman','Sophomore',
       ...:                               'Junior','Senior'],ordered=True)
    s.head()
    Out[25]: 
    0     Freshman
    1     Freshman
    2       Senior
    3    Sophomore
    4    Sophomore
    Name: Grade, dtype: category
    Categories (4, object): ['Freshman' < 'Sophomore' < 'Junior' < 'Senior']
    
    s.cat.as_unordered().head()
    Out[26]: 
    0     Freshman
    1     Freshman
    2       Senior
    3    Sophomore
    4    Sophomore
    Name: Grade, dtype: category
    Categories (4, object): ['Freshman', 'Sophomore', 'Junior', 'Senior']
    
    s = s.cat.reorder_categories(['Freshman','Sophomore',
       ...:                               'Junior','Senior'],ordered=False)
    s.head()
    Out[27]: 
    0     Freshman
    1     Freshman
    2       Senior
    3    Sophomore
    4    Sophomore
    Name: Grade, dtype: category
    Categories (4, object): ['Freshman', 'Sophomore', 'Junior', 'Senior']
    # 当order=False时,reorder_categories生成的时无序类别,并且order的默认值也为False
    
2.排序和比较

分类变量的排序:只需把列的类型修改为 category 后,再赋予相应的大小关系,就能正常地使用 sort_index sort_values

# 例如,对年级进行排序:

df.Grade = df.Grade.astype('category')
df.Grade = df.Grade.cat.reorder_categories(['Freshman',
   ...:                                             'Sophomore',
   ...:                                             'Junior',
   ...:                                             'Senior'],ordered=True)
df.sort_values('Grade').head() # 值排序
Out[34]: 
        Grade           Name  Gender  Height  Weight
0    Freshman   Gaopeng Yang  Female   158.9    46.0
105  Freshman      Qiang Shi  Female   164.5    52.0
96   Freshman  Changmei Feng  Female   163.8    56.0
88   Freshman   Xiaopeng Han  Female   164.1    53.0
81   Freshman    Yanli Zhang  Female   165.1    52.0

df.set_index('Grade').sort_index().head() # 索引排序
Out[37]: 
                   Name  Gender  Height  Weight
Grade                                          
Freshman   Gaopeng Yang  Female   158.9    46.0
Freshman      Qiang Shi  Female   164.5    52.0
Freshman  Changmei Feng  Female   163.8    56.0
Freshman   Xiaopeng Han  Female   164.1    53.0
Freshman    Yanli Zhang  Female   165.1    52.0

分类变量的比较操作分为两类:

  • 第一种是 == 或 != 关系的比较,比较的对象可以是标量或者同长度的 Series (或 list )
  • 第二种是 >,>=,<,<= 四类大小关系的比较,比较的对象和第一种类似,但是所有参与比较的元素必须属于原序列的 categories ,同时要和原序列具有相同的索引
res1 = df.Grade == 'Sophomore'
res1.head()
Out[39]: 
0    False
1    False
2    False
3     True
4     True
Name: Grade, dtype: bool

res2 = df.Grade == ['PhD']*df.shape[0]
res2.head()
Out[41]: 
0      False
1      False
2      False
3      False
4      False
Name: Grade, Length: 200, dtype: bool

res3 = df.Grade <= 'Sophomore'
res3.head()
Out[46]: 
0       True
1       True
2      False
3       True
4       True
Name: Grade, Length: 200, dtype: bool

res4 = df.Grade <= df.Grade.sample(frac=1).reset_index(drop=True) # 打乱后比较
res4.head()
Out[48]: 
0     True
1     True
2    False
3     True
4     True
Name: Grade, dtype: bool

三、区间类别

1.利用cut和qcut进行区间构造
  • cut:

    最重要的参数为**bin**,如果传入整数 n ,则代表把整个传入数组的按照最大和最小值等间距地分为 n 段。

    s = pd.Series([1,2])
    pd.cut(s,bins=2)
    Out[51]: 
    0    (0.999, 1.5]
    1      (1.5, 2.0]
    dtype: category
    Categories (2, interval[float64]): [(0.999, 1.5] < (1.5, 2.0]]
    pd.cut(s,bins=2,right=False)
    Out[52]: 
    0      [1.0, 1.5)
    1    [1.5, 2.001)
    dtype: category
    Categories (2, interval[float64]): [[1.0, 1.5) < [1.5, 2.001)]
    

    bins 的另一个常见用法是指定区间分割点的列表(使用 np.infty 可以表示无穷大):

    pd.cut(s,bins=[-np.infty,1.2,1.8,2.2,np.infty])
    Out[53]: 
    0    (-inf, 1.2]
    1     (1.8, 2.2]
    dtype: category
    Categories (4, interval[float64]): [(-inf, 1.2] < (1.2, 1.8] < (1.8, 2.2] < (2.2, inf]]
    

    另外两个常用参数labels retbins ,分别代表了区间的名字是否返回分割点(默认不返回)

    s = pd.Series([1,2])
    res = pd.cut(s,bins=2,labels=['small','big'],retbins=True)
    
    res[0]
    Out[56]: 
    0    small
    1      big
    dtype: category
    Categories (2, object): ['small' < 'big']
    
    s
    Out[57]: 
    0    1
    1    2
    dtype: int64
    
    res[1] # 该元素为返回的分割点
    Out[58]: array([0.999, 1.5  , 2.   ])
    
  • qcut:

    qcut cut 几乎没有差别,只是把 bins 参数变成的 q 参数, qcut 中的 q 是指 quantile 。这里的 q 为整数 n 时,指按照 n 等分位数把数据分箱,还可以传入浮点列表指代相应的分位数分割点:

    s = df.Weight
    pd.qcut(s,q=3).head()
    Out[60]: 
    0    (33.999, 48.0]
    1      (55.0, 89.0]
    2      (55.0, 89.0]
    3    (33.999, 48.0]
    4      (55.0, 89.0]
    Name: Weight, dtype: category
    Categories (3, interval[float64]): [(33.999, 48.0] < (48.0, 55.0] < (55.0, 89.0]]
    pd.qcut(s,q=[0,0.2,0.8,1]).head()
    Out[61]: 
    0      (44.0, 69.4]
    1      (69.4, 89.0]
    2      (69.4, 89.0]
    3    (33.999, 44.0]
    4      (69.4, 89.0]
    Name: Weight, dtype: category
    Categories (3, interval[float64]): [(33.999, 44.0] < (44.0, 69.4] < (69.4, 89.0]]
    
2.一般区间的构造
  • pd.Interval:

    对于某一个具体的区间而言,其具备三个要素:

    • 左端点

    • 右端点

    • 开闭状态,其中开闭状态可以指定 right, left, both, neither 中的一类:

      my_interval = pd.Interval(0,1,'right')
      my_interval
      Out[63]: Interval(0, 1, closed='right')
      

    其属性包含了mid, length, right, left, closed ,分别表示中点、长度、右端点、左端点和开闭状态。

    使用 in 可以判断元素是否属于区间:

    0.5 in my_interval
    Out[64]: True
    

    使用 overlaps 可以判断两个区间是否有交集:

    my_interval_2 = pd.Interval(0.5,1.5,'left')
    my_interval.overlaps(my_interval_2)
    Out[66]: True
    
  • pd.IntervalIndex 对象有四类方法生成,分别是:

    • from_breaks的功能类似于 cutqcut 函数,只不过后两个是通过计算得到的风格点,而前者是直接传入自定义的分割点

      pd.IntervalIndex.from_breaks([1,3,6,10],closed='both')
      Out[67]: 
      IntervalIndex([[1, 3], [3, 6], [6, 10]],
                    closed='both',
                    dtype='interval[int64]')
      
    • from_arrays是分别传入左端点和右端点的列表,适用于有交集并且知道起点和终点的情况

      pd.IntervalIndex.from_arrays(left = [1,3,6,10],
         ...:                              right = [5,4,9,11],
         ...:                              closed = 'neither')
      Out[68]: 
      IntervalIndex([(1, 5), (3, 4), (6, 9), (10, 11)],
                    closed='neither',
                    dtype='interval[int64]')
      
    • from_tuples传入的是起点和终点元组构成的列表:

      pd.IntervalIndex.from_tuples([(1,5),(3,4),(6,9),(10,11)],closed='neither')
      Out[69]: 
      IntervalIndex([(1, 5), (3, 4), (6, 9), (10, 11)],
                    closed='neither',
                    dtype='interval[int64]')
      pd.interval_range(start=1,end=5,periods=8)
      Out[70]: 
      IntervalIndex([(1.0, 1.5], (1.5, 2.0], (2.0, 2.5], (2.5, 3.0], (3.0, 3.5], (3.5, 4.0], (4.0, 4.5], (4.5, 5.0]],
                    closed='right',
                    dtype='interval[float64]')
      
    • 一个等差的区间序列由起点、终点、区间个数和区间长度决定interval_range中的 start, end, periods, freq 参数就对应了这四个量,从而就能构造出相应的区间:

      pd.interval_range(start=1,end=5,periods=8)
      Out[70]: 
      IntervalIndex([(1.0, 1.5], (1.5, 2.0], (2.0, 2.5], (2.5, 3.0], (3.0, 3.5], (3.5, 4.0], (4.0, 4.5], (4.5, 5.0]],
                    closed='right',
                    dtype='interval[float64]')
               
      pd.interval_range(end=8,periods=8,freq=0.5)
      Out[71]: 
      IntervalIndex([(4.0, 4.5], (4.5, 5.0], (5.0, 5.5], (5.5, 6.0], (6.0, 6.5], (6.5, 7.0], (7.0, 7.5], (7.5, 8.0]],
                    closed='right',
                    dtype='interval[float64]')
      
  • 除此之外,如果直接使用 pd.IntervalIndex([…], closed=…) ,把 Interval 类型的列表组成传入其中转为区间索引,那么所有的区间会被强制转为指定的 closed 类型,因为 pd.IntervalIndex 只允许存放同一种开闭区间的 Interval 对象:

    pd.IntervalIndex([my_interval,my_interval_2],closed='left')
    Out[74]: 
    IntervalIndex([[0.0, 1.0), [0.5, 1.5)],
                  closed='left',
                  dtype='interval[float64]')
    
3.区间的属性与方法

IntervalIndex 上也定义了一些有用的属性和方法。同时,如果想要具体利用 cut 或者 qcut 的结果进行分析,那么需要先将其转为该种索引类型

id_interval = pd.IntervalIndex(pd.cut(s,3))
id_interval
Out[76]: 
IntervalIndex([(33.945, 52.333], (52.333, 70.667], (70.667, 89.0], (33.945, 52.333], (70.667, 89.0] ... (33.945, 52.333], (33.945, 52.333], (33.945, 52.333], (70.667, 89.0], (33.945, 52.333]],
              closed='right',
              name='Weight',
              dtype='interval[float64]')

与单个Interval类型相似,IntervalIndex有若干属性:

id_demo = id_interval[:5]
id_demo
Out[78]: 
IntervalIndex([(33.945, 52.333], (52.333, 70.667], (70.667, 89.0], (33.945, 52.333], (70.667, 89.0]],
              closed='right',
              name='Weight',
              dtype='interval[float64]')
  • left:左端点

    id_demo.left
    Out[79]: Float64Index([33.945, 52.333, 70.667, 33.945, 70.667], dtype='float64')
    
  • right:右端点

    id_demo.right
    Out[80]: Float64Index([52.333, 70.667, 89.0, 52.333, 89.0], dtype='float64')
    
  • mid:均值

    id_demo.mid
    Out[81]: Float64Index([43.138999999999996, 61.5, 79.8335, 43.138999999999996, 79.8335], dtype='float64')
    
  • length:区间长度

    id_demo.length
    Out[82]: 
    Float64Index([18.387999999999998, 18.334000000000003, 18.333,
                  18.387999999999998, 18.333],
                 dtype='float64')
    

IntervalIndex 还有两个常用方法,包括 containsoverlaps ,分别指逐个判断每个区间是否包含某元素,以及是否和一个 pd.Interval 对象有交集:

id_demo.contains(4)
Out[83]: array([False, False, False, False, False])

id_demo.overlaps(pd.Interval(40,60))
Out[84]: array([ True,  True, False,  True, False])
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值