Data Whale第20期组队学习 Pandas学习—分类数据

一、cat对象

1.1 cat对象的属性

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

import pandas as pd
import  numpy as np
df= pd.read_csv('D:/binchen/txzq/data/learn_pandas.csv',usecols = ['Grade', 'Name', 'Gender', 'Height', 'Weight'])
Sg=df.Grade.astype('category')
print("Sg.head()=\n",Sg.head())
# Sg.head()=
#  0     Freshman
# 1     Freshman
# 2       Senior
# 3    Sophomore
# 4    Sophomore
# Name: Grade, dtype: category
# Categories (4, object): ['Freshman', 'Junior', 'Senior', 'Sophomore']
"在一个分类类型的 Series 中定义了 cat 对象,定义了一些属性和方法来进行分类类别的操作。"
print("Sg.cat=",Sg.cat)
# Sg.cat= <pandas.core.arrays.categorical.CategoricalAccessor object at 0x0000020B6A6D3B00>
print("Sg.cat.categories=",Sg.cat.categories)
# Sg.cat.categories= Index(['Freshman', 'Junior', 'Senior', 'Sophomore'], dtype='object')
print("Sg.cat.ordered=",Sg.cat.ordered)
# Sg.cat.ordered= False

"每一个序列的类别会被赋予唯一的整数编号,它们的编号取决于 cat.categories 中的顺序,该属性可以通过 codes 访问"
print("Sg.cat.codes.head()=",Sg.cat.codes.head())
# Sg.cat.codes.head()= 0    0
# 1    0
# 2    2
# 3    3
# 4    3
# dtype: int8









1.2 类别的增加、删除和修改

通过 cat 对象的 categories 属性能够完成对类别的查询,应该如何进行“增改查删”的其他三个操作呢?首先,对于类别的增加可以使用 add_categories ;若要删除某一个类别可以使用 remove_categories ,同时所有原来序列中的该类会被设置为缺失;可以使用 set_categories 直接设置序列的新类别,原来的类别中如果存在元素不属于新类别,那么会被设置为缺失。如果想要删除未出现在序列中的类别,可以使用 remove_unused_categories 来实现;最后,“增改查删”中还剩下修改的操作,这可以通过 rename_categories 方法完成,同时需要注意的是,这个方法会对原序列的对应值也进行相应修改。

"可以使用 add_categories 增加类别"
S1=Sg.cat.add_categories('Graduate') # 增加一个毕业生类别
print("S1.cat.categories=",S1.cat.categories)
# S1.cat.categories= Index(['Freshman', 'Junior', 'Senior', 'Sophomore', 'Graduate'], dtype='object')
"删除大一的类别使用 remove_categories"
S2=Sg.cat.remove_categories('Freshman')
print("S2.cat.categories=",S2.cat.categories)
# S2.cat.categories= Index(['Junior', 'Senior', 'Sophomore'], dtype='object')
print("S2.head()=",S2.head())
# S2.head()= 0          NaN
# 1          NaN
# 2       Senior
# 3    Sophomore
# 4    Sophomore
# Name: Grade, dtype: category
# Categories (3, object): ['Junior', 'Senior', 'Sophomore']
"使用 set_categories 直接设置序列的新类别"
S3=Sg.cat.set_categories(['Sophomore','PhD']) # 新类别为大二学生和博士
print("S3.cat.categories=",S3.cat.categories)
# S3.cat.categories= Index(['Sophomore', 'PhD'], dtype='object')
print("S3.head()=",S3.head())
# S3.cat.categories= Index(['Sophomore', 'PhD'], dtype='object')
# S3.head()= 0          NaN
# 1          NaN
# 2          NaN
# 3    Sophomore
# 4    Sophomore
# Name: Grade, dtype: category
# Categories (2, object): ['Sophomore', 'PhD']
"使用 remove_unused_categories 删除未出现在序列中的类别"
S4=S3.cat.remove_unused_categories() # 移除了未出现的博士生类别
print("S4.cat.categories=",S4.cat.categories)
# S4.cat.categories= Index(['Sophomore'], dtype='object')
"使用rename_categories 方法完成修改的操作"
S5=S3.cat.rename_categories({'Sophomore':'本科二年级学生'})
print("S5.head()=",S5.head())
# S5.head()= 0        NaN
# 1        NaN
# 2        NaN
# 3    本科二年级学生
# 4    本科二年级学生
# Name: Grade, dtype: category
# Categories (2, object): ['本科二年级学生', 'PhD']

二、有序分类

2.1 序的建立

有序类别和无序类别可以通过 as_unordered 和 reorder_categories 互相转化,需要注意的是后者传入的参数必须是由当前序列的无需类别构成的列表,不能够增加新的类别,也不能缺少原来的类别,并且必须指定参数 ordered=True ,否则方法无效。例如,对年级高低进行相对大小的类别划分,然后再恢复无序状态。

S6 = df.Grade.astype('category')
S6=S6.cat.reorder_categories(['Freshman', 'Sophomore',
                              'Junior', 'Senior'],ordered=True)
print("S6.head()=",S6.head())
# S6.head()= 0     Freshman
# 1     Freshman
# 2       Senior
# 3    Sophomore
# 4    Sophomore
# Name: Grade, dtype: category
# Categories (4, object): ['Freshman' < 'Sophomore' < 'Junior' < 'Senior']
print("S6.cat.as_unordered().head()=",S6.cat.as_unordered().head())
# S6.cat.as_unordered().head()= 0     Freshman
# 1     Freshman
# 2       Senior
# 3    Sophomore
# 4    Sophomore
# Name: Grade, dtype: category
# Categories (4, object): ['Freshman', 'Sophomore', 'Junior', 'Senior']

注意

如果不想指定 ordered=True 参数,那么可以先用 s.cat.as_ordered() 转化为有序类别,再利用 reorder_categories 进行具体的相对大小调整。

2.2 排序和比较

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

DF1= df.Grade.astype('category')
DF1=DF1.cat.reorder_categories(['Freshman','Sophomore','Junior','Senior'],ordered=True)
print("df.sort_values('Grade').head()=\n",df.sort_values('Grade').head())
# df.sort_values('Grade').head()=
#          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
print("df.set_index('Grade').sort_index().head()=\n",df.set_index('Grade').sort_index().head())
# df.set_index('Grade').sort_index().head()=
#                     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
res1 = DF1 == 'Sophomore'
print("res1.head()=",res1.head())
# res1.head()= 0    False
# 1    False
# 2    False
# 3     True
# 4     True
# Name: Grade, dtype: bool
res2 = DF1 == ['PhD']*df.shape[0]
print("res2.head()=",res2.head())
# res2.head()= 0    False
# 1    False
# 2    False
# 3    False
# 4    False
# Name: Grade, dtype: bool
res3 = DF1 <= 'Sophomore'
print("res3.head()=",res3.head())
# res3.head()= 0     True
# 1     True
# 2    False
# 3     True
# 4     True
# Name: Grade, dtype: bool
res4 = DF1 <= DF1.sample(frac=1).reset_index(drop=True) # 打乱后比较
print("res4.head()=",res4.head())
# res4.head()= 0     True
# 1     True
# 2     True
# 3    False
# 4     True
# Name: Grade, dtype: bool

三、区间类别

3.1 利用cut和qcut进行区间构造

区间是一种特殊的类别,在实际数据分析中,区间序列往往是通过 cut 和 qcut 方法进行构造的,这两个函数能够把原序列的数值特征进行装箱,即用区间位置来代替原来的具体数值。
首先介绍 cut 的常见用法:最重要的参数是 bin ,如果传入整数 n ,则代表把整个传入数组的按照最大和最小值等间距地分为 n 段。由于区间默认是左开右闭,需要进行调整把最小值包含进去,在 pandas 中的解决方案是在值最小的区间左端点再减去 0.001*(max-min) ,因此如果对序列 [1,2] 划分为2个箱子时,第一个箱子的范围 (0.999,1.5] ,第二个箱子的范围是 (1.5,2] 。如果需要指定左闭右开时,需要把 right 参数设置为 False ,相应的区间调整方法是在值最大的区间右端点再加上 0.001*(max-min) 。
bins 的另一个常见用法是指定区间分割点的列表(使用 np.infty 可以表示无穷大)
另外两个常用参数为 labels 和 retbins ,分别代表了区间的名字和是否返回分割点(默认不返回)
从用法上来说, qcut 和 cut 几乎没有差别,只是把 bins 参数变成的 q 参数, qcut 中的 q 是指 quantile 。这里的 q 为整数 n 时,指按照 n 等分位数把数据分箱,还可以传入浮点列表指代相应的分位数分割点。

S7=pd.Series([1,2,3,4])
print("pd.cut(S7, bins=2)=",pd.cut(S7, bins=2))
# pd.cut(S7, bins=2)= 0    (0.997, 2.5]
# 1    (0.997, 2.5]
# 2      (2.5, 4.0]
# 3      (2.5, 4.0]
# dtype: category
# Categories (2, interval[float64]): [(0.997, 2.5] < (2.5, 4.0]]
print("pd.cut(S7, bins=2, right=False)=",pd.cut(S7, bins=2, right=False))
# pd.cut(S7, bins=2, right=False)= 0      [1.0, 2.5)
# 1      [1.0, 2.5)
# 2    [2.5, 4.003)
# 3    [2.5, 4.003)
# dtype: category
# Categories (2, interval[float64]): [[1.0, 2.5) < [2.5, 4.003)]
print("",pd.cut(S7, bins=[-np.infty, 1.2, 1.8, 2.2, np.infty]))
# Categories (2, interval[float64]): [[1.0, 2.5) < [2.5, 4.003)]
#  0    (-inf, 1.2]
# 1     (1.8, 2.2]
# 2     (2.2, inf]
# 3     (2.2, inf]
# dtype: category
# Categories (4, interval[float64]): [(-inf, 1.2] < (1.2, 1.8] < (1.8, 2.2] < (2.2, inf]]
res=pd.cut(S7, bins=2, labels=['small', 'big'], retbins=True)
print("res[0]=",res[0])
# res[0]= 0    small
# 1    small
# 2      big
# 3      big
# dtype: category
# Categories (2, object): ['small' < 'big']
S8=df.Weight
print("pd.qcut(S8, q=5).head()=",pd.qcut(S8, q=5).head())
# pd.qcut(S8, q=5).head()= 0      (44.0, 49.0]
# 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 (5, interval[float64]): [(33.999, 44.0] < (44.0, 49.0] < (49.0, 53.0] < (53.0, 69.4] <
#                                     (69.4, 89.0]]
print("pd.qcut(S7, q=[0.1,0.5,0.8,1]).head()=",pd.qcut(S7, q=[0.1,0.5,0.8,1]).head())
# pd.qcut(S7, q=[0.1,0.5,0.8,1]).head()= 0                          NaN
# 1    (1.2990000000000002, 2.5]
# 2                   (2.5, 3.4]
# 3                   (3.4, 4.0]
# dtype: category
# Categories (3, interval[float64]): [(1.2990000000000002, 2.5] < (2.5, 3.4] < (3.4, 4.0]]

3.2 一般区间的构造

对于某一个具体的区间而言,其具备三个要素,即左端点、右端点和端点的开闭状态,其中开闭状态可以指定 right, left, both, neither 中的一类。其属性包含了 mid, length, right, left, closed ,分别表示中点、长度、右端点、左端点和开闭状态。


my_interval = pd.Interval(0, 1, 'right')
print("my_interval:",my_interval)
# my_interval: (0, 1]
print(0.5 in my_interval,1.5 in my_interval)# 使用 in 可以判断元素是否属于区间
# True False
my_interval_2 = pd.Interval(0.5, 1.5, 'left')
print(my_interval.overlaps(my_interval_2))#使用 overlaps 可以判断两个区间是否有交集
#True

一般而言, pd.IntervalIndex 对象有四类方法生成,分别是 from_breaks, from_arrays, from_tuples, interval_range ,它们分别应用于不同的情况:

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


print("pd.IntervalIndex.from_breaks([1,3,6,10,12,15], closed='both')=",
      pd.IntervalIndex.from_breaks([1,3,6,10,12,15], closed='both'))
# pd.IntervalIndex.from_breaks([1,3,6,10,12,15], closed='both')= IntervalIndex([[1, 3], [3, 6], [6, 10], [10, 12], [12, 15]],
#               closed='both',
#               dtype='interval[int64]')
"from_arrays 是分别传入左端点和右端点的列表,适用于有交集并且知道起点和终点的情况"
print("pd.IntervalIndex.from_arrays(left = [1,3,6,10],right = [5,4,9,11],closed = 'neither')=",
      pd.IntervalIndex.from_arrays(left = [1,3,6,10],right = [5,4,9,11],closed = 'neither'))
# pd.IntervalIndex.from_arrays(left = [1,3,6,10],right = [5,4,9,11],closed = 'neither')= IntervalIndex([(1, 5), (3, 4), (6, 9), (10, 11)],
#               closed='neither',
#               dtype='interval[int64]')
"from_tuples 传入的是起点和终点元组构成的列表"
print("pd.IntervalIndex.from_tuples([(1,5),(3,4),(6,9),(10,11)],closed='neither')",
      pd.IntervalIndex.from_tuples([(1,5),(3,4),(6,9),(10,11)],closed='neither'))
# pd.IntervalIndex.from_tuples([(1,5),(3,4),(6,9),(10,11)],closed='neither') IntervalIndex([(1, 5), (3, 4), (6, 9), (10, 11)],
#               closed='neither',
#               dtype='interval[int64]')

一个等差的区间序列由起点、终点、区间个数和区间长度决定,其中三个量确定的情况下,剩下一个量就确定了, interval_range 中的 start, end, periods, freq 参数就对应了这四个量,从而就能构造出相应的区间。

print("pd.interval_range(start=1,end=8,periods=12)=",pd.interval_range(start=1,end=8,periods=12))
# pd.interval_range(start=1,end=8,periods=12)= IntervalIndex([(1.0, 1.5833333333333335], (1.5833333333333335, 2.166666666666667], (2.166666666666667, 2.75], (2.75, 3.3333333333333335], (3.3333333333333335, 3.916666666666667] ... (5.083333333333334, 5.666666666666667], (5.666666666666667, 6.25], (6.25, 6.833333333333334], (6.833333333333334, 7.416666666666667], (7.416666666666667, 8.0]],
#               closed='right',
#               dtype='interval[float64]')
print("pd.interval_range(end=5,periods=10,freq=0.5)",pd.interval_range(end=5,periods=10,freq=0.5))
# pd.interval_range(end=5,periods=10,freq=0.5) IntervalIndex([(0.0, 0.5], (0.5, 1.0], (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.IntervalIndex([…], closed=…) ,把 Interval 类型的列表组成传入其中转为区间索引,那么所有的区间会被强制转为指定的 closed 类型,因为 pd.IntervalIndex 只允许存放同一种开闭区间的 Interval 对象。

print("pd.IntervalIndex([my_interval, my_interval_2], closed='left')",
      pd.IntervalIndex([my_interval, my_interval_2], closed='left') )
# pd.IntervalIndex([my_interval, my_interval_2], closed='left') IntervalIndex([[0.0, 1.0), [0.5, 1.5)],
#               closed='left',
#               dtype='interval[float64]')

3.3 区间的属性与方法

IntervalIndex 上也定义了一些有用的属性和方法。同时,如果想要具体利用 cut 或者 qcut 的结果进行分析,那么需要先将其转为该种索引类型,与单个 Interval 类型相似, IntervalIndex 有若干常用属性: left, right, mid, length ,分别表示左右端点、两端点均值和区间长度。

id_interval = pd.IntervalIndex(pd.cut(S8, 3))
id_demo = id_interval[:5] # 选出前5个展示
print("id_demo=",id_demo)
# id_demo= 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]')

print("id_demo.left=",id_demo.left)
# id_demo.left= Float64Index([33.945, 52.333, 70.667, 33.945, 70.667], dtype='float64')
print("id_demo.right=",id_demo.right)
# id_demo.right= Float64Index([52.333, 70.667, 89.0, 52.333, 89.0], dtype='float64')
print("id_demo.mid=",id_demo.mid)
# id_demo.mid= Float64Index([43.138999999999996, 61.5, 79.8335, 43.138999999999996, 79.8335], dtype='float64')
print("id_demo.length=",id_demo.length)
# id_demo.length= Float64Index([18.387999999999998, 18.334000000000003, 18.333,
#               18.387999999999998, 18.333],
#              dtype='float64')
"IntervalIndex 还有两个常用方法,包括 contains 和 overlaps ,"
"分别指逐个判断每个区间是否包含某元素,以及是否和一个 pd.Interval 对象有交集。"
print("id_demo.contains(4)=",id_demo.contains(4))
# id_demo.contains(4)= [False False False False False]
print("id_demo.overlaps(pd.Interval(40,60))=",id_demo.overlaps(pd.Interval(40,60)))
# id_demo.overlaps(pd.Interval(40,60))= [ True  True False  True False]

参考文献

1、https://datawhalechina.github.io/joyful-pandas/build/html/%E7%9B%AE%E5%BD%95/ch9.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
鲸鱼算法(Whale Algorithm,WA)是一种仿生启发式优化算法,它模拟了鲸鱼群体的行为来求解优化问题。支持向量机(Support Vector Machine,SVM)是一种机器学习算法,被广泛用于数据分类任务中。下面给出基于鲸鱼算法优化支持向量机实现数据分类的Matlab代码示例: ```matlab % 数据准备 load data.mat % 假设已经加载了训练数据data为输入特征矩阵,labels为标签向量 C = 10; % 惩罚系数,可根据具体问题调整 % 计算数据维度和样本数 [num_samples, num_features] = size(data); % 初始化鲸鱼算法参数 max_iterations = 100; % 最大迭代次数 num_whales = 10; % 鲸鱼数量 dim = num_features + 1; % 参数维度,包括截距项 X = [data, ones(num_samples, 1)]; % 加上截距项 % 初始化鲸鱼位置 positions = rand(num_whales, dim); % 随机初始化鲸鱼位置 % 开始优化过程 for iter = 1:max_iterations for i = 1:num_whales % 计算支持向量机的目标函数值 w = positions(i, 1:num_features)'; % 提取权重 b = positions(i, num_features+1); % 提取截距项 y_pred = X * [w; b]; hinge_loss = max(0, 1 - labels .* y_pred); % Hinge Loss svm_obj = 0.5 * w' * w + C * sum(hinge_loss); % 目标函数值 % 更新鲸鱼位置 a = 2 * iter / max_iterations - 1; % 用于控制搜索范围 A = 2 * a * rand() - a; C = 2 * rand(); if abs(A) < 1 p = 2 * rand(size(positions(i, :))) - 1; D = abs(C * positions(i, :) - positions(i, :)); updated_positions(i, :) = positions(i, :) + A * D .* p; else chosen_whale = positions(randi([1,num_whales]), :); D = abs(C * chosen_whale - positions(i, :)); updated_positions(i, :) = chosen_whale + A * D; end % 边界约束,防止参数超出取值范围 updated_positions(i, :) = max(min(updated_positions(i, :), 1), -1); % 更新最优解(最小目标函数值) if svm_obj < best_obj best_obj = svm_obj; best_positions = updated_positions(i, :); end end % 更新鲸鱼位置 positions = updated_positions; end % 得到最优的权重和截距项 best_w = best_positions(1:num_features)'; best_b = best_positions(num_features+1); % 使用最优权重和截距项进行分类预测 y_pred = X * [best_w; best_b]; y_pred(y_pred > 0) = 1; y_pred(y_pred <= 0) = -1; % 计算分类精度 accuracy = sum(y_pred == labels) / num_samples; disp(['分类精度:', num2str(accuracy)]); ``` 以上是基于鲸鱼算法优化支持向量机实现数据分类的Matlab代码示例。该代码通过迭代更新鲸鱼位置来优化支持向量机的目标函数值,得到最优的权重和截距项,并使用其对数据进行分类预测。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值