主要内容

本页翻译不是最新的。点击此处可查看最新英文版本。

categorical

数组,包含分配给类别的值

说明

categorical 是为一组有限的离散类别(例如 HighMedLow)赋值的数据类型。这些类别可以采用您指定的数学排序,例如 High > Med > Low,但这并非必须。分类数组可用来有效地存储并方便地处理非数值数据,同时还为数值赋予有意义的名称。分类数组的常见用法是用来定义构成表的各组行。

创建对象

要创建一个 categorical 数组,请执行以下操作:

  • 使用如下所述的 categorical 函数。

  • 使用 discretize 函数对连续数据分 bin。以分类数组形式返回这些 bin。

  • 将两个分类数组相乘。乘积是一个分类数组,其类别是两个操作数的类别的所有可能组合。

描述

B = categorical(A) 根据输入数组创建分类数组。输出数组的类别是输入数组中经过排序的唯一值。

示例

B = categorical(A,valueset)valueset 中的每个值创建一个类别。B 的类别与 valueset 的值具有相同的顺序。

您可以使用 valueset 来包含 A 中不存在的值的类别。反之,如果 A 包含 valueset 中不存在的任何值,则 B 的对应元素为未定义。

示例

B = categorical(A,valueset,catnames) 通过将 valueset 中的类别值与 catnames 中的对应名称进行匹配来命名类别。

示例

B = categorical(A,___,Name=Value) 用于在上述语法中的输入参量之外另使用一个或多个名称-值参量指定选项。例如,要指示类别采用数学排序,请将 Ordinal 设置为 true

示例

输入参量

全部展开

输入数组,指定为数值数组、逻辑数组、分类数组、日期时间数组、持续时间数组、字符串数组或字符向量元胞数组。

categorical 函数会删除作为字符串或字符向量的输入值中的前导和尾随空格。

如果输入 A 包含缺失值,则输出数组的对应元素未定义,并显示为 <undefined>categorical 函数可将下列值转换为未定义的类别值:

  • 数值数组和持续时间数组中的 NaN

  • 字符串数组中的缺失字符串 (<missing>) 或空字符串 ("")

  • 字符向量元胞数组中的空字符向量 ('')

  • 日期时间数组中的 NaT

  • 分类数组中未定义的值 (<undefined>)

对于未定义的值,输出数组没有对应的类别。要为缺失值或未定义的值创建显式类别,必须在 catnames 中给出所需的类别名称,并在 valueset 中给出缺失值作为对应的值。

输入 A 还可以是具有以下类方法的对象数组:

  • unique

  • eq

类别,指定为由唯一值组成的向量。valueset 的数据类型和输入数组的数据类型必须相同,除非输入是字符串数组。在这种情况下,valueset 可以是字符串数组或字符向量元胞数组。

categorical 函数会删除作为字符串或字符向量的 valueset 元素中的前导和尾随空格。

类别名称,指定为字符串数组或字符向量元胞数组。如果不指定 catnames 输入参量,categorical 将使用 valueset 中的值作为类别名称。

类别名称不能包含缺失字符串 (<missing>)、空字符串 ("") 或空字符向量 ('')。

要将输入数组中的多个不同值合并到输出数组中的单个类别中,请包括与这些值对应的、完全一样的名称。

名称-值参数

全部展开

将可选的参量对组指定为 Name1=Value1,...,NameN=ValueN,其中 Name 是参量名称,Value 是对应的值。名称-值参量必须出现在其他参量之后,但参量对组的顺序无关紧要。

在 R2021a 之前,使用逗号分隔每个名称和值,并用引号将 Name 引起来。

示例: categorical(A,Ordinal=true) 指定类别具有数学排序方式。

有序变量标志,指定为数值或逻辑值 0 (false) 或 1 (true)。

0 (false)

categorical 创建一个无序的分类数组,此为默认行为。

输出数组的类别没有数学排序方式。因此,您只能比较输出中的值是否相等。您无法使用任何其他关系运算符来比较这些值。

1 (true)

categorical 创建一个有序分类数组。

输出数组的类别具有数学排序方式,这样指定的第一个类别是最小的类别,最后一个类别是最大的类别。除了比较值的相等性之外,您还可以使用关系运算符比较输出中的值,例如小于和大于。还可以对有序分类数组使用 minmax 函数。

有关详细信息,请参阅 有序分类数组

受保护类别标志,指定为数值或逻辑值 0 (false) 或 1 (true)。

有序分类数组的类别始终受保护。如果将 Ordinal 设置为 true,则 Protected 的默认值也是 true。否则,Protected 的默认值是 false

0 (false)

在向输出数组赋新值时,类别会自动更新。因此,您可以合并具有不同类别的(非有序)分类数组。类别会相应更新以包括两个数组中的类别。

1 (true)

在向输出数组赋新值时,这些值必须属于现有类别之一。因此,只能合并具有相同类别的数组。要向输出添加新类别,必须使用 addcats 函数。

示例

全部折叠

从气象站代码列表创建一个分类数组。然后将其添加到温度读数表中。使用该分类数组帮助您按类别分析表中的数据。

首先,创建一个气象站代码数组。

Stations = ["S1" "S2" "S1" "S3" "S2"]
Stations = 1×5 string
    "S1"    "S2"    "S1"    "S3"    "S2"

要根据气象站代码创建一个分类数组,请使用 categorical 函数。

Stations = categorical(Stations)
Stations = 1×5 categorical
     S1      S2      S1      S3      S2 

显示类别。三个站代码是类别。

categories(Stations)
ans = 3×1 cell
    {'S1'}
    {'S2'}
    {'S3'}

现在创建一个包含天气数据的表。该表包含温度、日期和站代码。

Temperatures = [58;72;56;90;76];
Dates = datetime(["2017-04-17";"2017-04-18";"2017-04-30";"2017-05-01";"2017-04-27"]);
Stations = Stations';
tempReadings = table(Temperatures,Dates,Stations)
tempReadings=5×3 table
    Temperatures       Dates       Stations
    ____________    ___________    ________

         58         17-Apr-2017       S1   
         72         18-Apr-2017       S2   
         56         30-Apr-2017       S1   
         90         01-May-2017       S3   
         76         27-Apr-2017       S2   

按气象站对表中的数据进行分类。例如,返回包含站 S2 的数据的表行。使用逻辑索引数组对表进行索引,其中 Stations 等于 S2

TF = (tempReadings.Stations == "S2")
TF = 5×1 logical array

   0
   1
   0
   0
   1

tempReadings(TF,:)
ans=2×3 table
    Temperatures       Dates       Stations
    ____________    ___________    ________

         72         18-Apr-2017       S2   
         76         27-Apr-2017       S2   

为了找到与气象站相关联的数据模式,需要创建一个按气象站划分的温度读数的散点图。

scatter(tempReadings,"Stations","Temperatures","filled")

Figure contains an axes object. The axes object with xlabel Stations, ylabel Temperatures contains an object of type scatter.

将字符串数组转换为分类数组。指定该分类数组具有一组类别,其中包含原始数组中不存在的值。

首先,创建一个包含一组重复值的字符串数组。

A = ["red" "blue" "blue" "blue" "blue" "red"]
A = 1×6 string
    "red"    "blue"    "blue"    "blue"    "blue"    "red"

将此字符串数组转换为分类数组。指定其类别。包括 green 作为一个类别。

valueset = ["blue" "red" "green"];
B = categorical(A,valueset)
B = 1×6 categorical
     red      blue      blue      blue      blue      red 

显示分类数组的类别。它包含一个并非来自输入字符串数组的类别。

categories(B)
ans = 3×1 cell
    {'blue' }
    {'red'  }
    {'green'}

创建一个数值数组。

A = [1 3 2; 2 1 3; 3 1 2]
A = 3×3

     1     3     2
     2     1     3
     3     1     2

将该数值数组转换为分类数组。指定类别的值和名称。

B = categorical(A,[1 2 3],["red" "green" "blue"])
B = 3×3 categorical
     red        blue      green 
     green      red       blue  
     blue       red       green 

显示类别。

categories(B)
ans = 3×1 cell
    {'red'  }
    {'green'}
    {'blue' }

B 不是有序的分类数组。因此,您只能使用相等运算符 ==~= 比较 B 中的值。

找出属于类别 red 的元素。使用逻辑索引访问这些元素。

TF = (B == "red")
TF = 3×3 logical array

   1   0   0
   0   1   0
   0   1   0

B(TF)
ans = 3×1 categorical
     red 
     red 
     red 

默认情况下,categorical 函数将缺失值(如 NaNNaT、空字符串和缺失字符串)转换为未定义的分类值。不过,当您调用 categorical 时,您可以指定缺失值所属的类别。

例如,创建一个包含空字符串和缺失字符串的字符串数组。

A = ["hi" "lo" missing "" "lo" "lo" "hi"]
A = 1×7 string
    "hi"    "lo"    <missing>    ""    "lo"    "lo"    "hi"

首先,将该字符串数组转换为包含未定义元素的分类数组。

C = categorical(A)
C = 1×7 categorical
     hi      lo      <undefined>      <undefined>      lo      lo      hi 

categories(C)
ans = 2×1 cell
    {'hi'}
    {'lo'}

然后再次转换它。但是,这次指定 INDEF 作为缺失字符串的类别。

C = categorical(A,["lo" "hi" missing],["lo" "hi" "INDEF"])
C = 1×7 categorical
     hi      lo      INDEF      <undefined>      lo      lo      hi 

categories(C)
ans = 3×1 cell
    {'lo'   }
    {'hi'   }
    {'INDEF'}

指定 INDEF 作为缺失字符串和空字符串的类别。

C = categorical(A,["lo" "hi" missing ""],["lo" "hi" "INDEF" "INDEF"])
C = 1×7 categorical
     hi      lo      INDEF      INDEF      lo      lo      hi 

categories(C)
ans = 3×1 cell
    {'lo'   }
    {'hi'   }
    {'INDEF'}

创建一个 5×2 的数值数组。

A = [3 2;3 3;3 2;2 1;3 2]
A = 5×2

     3     2
     3     3
     3     2
     2     1
     3     2

A 转换为有序分类数组,其中 123 分别表示类别 childadultsenior

valueset = [1 2 3];
catnames = ["child" "adult" "senior"];
B = categorical(A,valueset,catnames,Ordinal=true)
B = 5×2 categorical
     senior      adult  
     senior      senior 
     senior      adult  
     adult       child  
     senior      adult  

由于 B 是有序数组,B 的类别具有数学排序方式 child < adult < senior。您可以对有序分类值使用所有关系运算符。例如,返回值大于 adult 的元素。

TF = B > "adult"
TF = 5×2 logical array

   1   0
   1   1
   1   0
   0   0
   1   0

B(TF)
ans = 5×1 categorical
     senior 
     senior 
     senior 
     senior 
     senior 

您可以通过创建一个 NaN 数组并将其转换为分类数组来预分配任意大小的分类数组。预分配数组后,可以通过指定类别名称并将类别添加到数组来初始化其类别。

首先创建一个 NaN 数组。您可以创建任意大小的数组。例如,创建一个由 NaN 值组成的 2×4 数组。

A = NaN(2,4)
A = 2×4

   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN

然后通过转换 NaN 数组来预分配分类数组。categorical 函数将 NaN 转换为未定义的分类值。正如 NaN 表示“不是数字”,<undefined> 表示不属于某个类别的分类值。

A = categorical(A)
A = 2×4 categorical
     <undefined>      <undefined>      <undefined>      <undefined> 
     <undefined>      <undefined>      <undefined>      <undefined> 

事实上,此时 A 没有类别。

categories(A)
ans =

  0×0 empty cell array

要初始化 A 的类别,请指定类别名称,并使用 addcats 函数将它们添加到 A 中。例如,添加 smallmediumlarge 作为 A 的三个类别。

A = addcats(A,["small" "medium" "large"])
A = 2×4 categorical
     <undefined>      <undefined>      <undefined>      <undefined> 
     <undefined>      <undefined>      <undefined>      <undefined> 

虽然 A 的元素是未定义的值,但类别已由 addcats 初始化。

categories(A)
ans = 3×1 cell
    {'small' }
    {'medium'}
    {'large' }

现在 A 已经有了类别,您可以将定义的分类值指定为 A 的元素。

A(1) = "medium";
A(8) = "small";
A(3:5) = "large"
A = 2×4 categorical
     medium           large      large            <undefined> 
     <undefined>      large      <undefined>      small       

推荐使用 discretize 函数为连续数据创建若干类别,尤其是当输入值间距很小时。当两个值之间的差约小于 5e-5 时,其间距很小。当值的间距很小时,categorical 函数无法根据值创建唯一类别名称。

创建一个包含 100 个随机数的数值数组。

X = rand(100,1)
X = 100×1

    0.8147
    0.9058
    0.1270
    0.9134
    0.6324
    0.0975
    0.2785
    0.5469
    0.9575
    0.9649
    0.1576
    0.9706
    0.9572
    0.4854
    0.8003
      ⋮

要通过分 bin 将这些数字分成三个类别,请使用 discretize。为 bin 指定 bin 边界和类别名称。

C = discretize(X,[0 .25 .75 1],"categorical",["small" "medium" "large"])
C = 100×1 categorical
     large 
     large 
     small 
     large 
     medium 
     small 
     medium 
     medium 
     large 
     large 
     small 
     large 
     large 
     medium 
     large 
     small 
     medium 
     large 
     large 
     large 
     medium 
     small 
     large 
     large 
     medium 
     large 
     medium 
     medium 
     medium 
     small 
      ⋮

绘制这三个类别的数据的直方图。

histogram(C)

Figure contains an axes object. The axes object contains an object of type categoricalhistogram.

当您将两个分类数组相乘时,将得到一个包含一组新类别的分类数组。新类别是根据两个原始分类数组的类别创建的所有有序对组。这组所有可能的类别组合也称为两个原始类别组的笛卡尔积

例如,创建两个分类数组。这些数组列出六位患者的血型和 Rh 因子。

bloodGroups = categorical(["A" "AB" "O" "O" "A" "A"], ...
                          ["A" "B" "AB" "O"])
bloodGroups = 1×6 categorical
     A      AB      O      O      A      A 

Rhfactors = categorical(["+" "+" "-" "-" "+" "+"])
Rhfactors = 1×6 categorical
     +      +      -      -      +      + 

显示这两个数组的类别。虽然这两个分类数组具有相同数量的元素,但它们可以具有不同数量的类别。

categories(bloodGroups)
ans = 4×1 cell
    {'A' }
    {'B' }
    {'AB'}
    {'O' }

categories(Rhfactors)
ans = 2×1 cell
    {'+'}
    {'-'}

将这两个分类数组相乘。乘积的元素来自输入数组中对应元素的组合。

bloodTypes = bloodGroups .* Rhfactors
bloodTypes = 1×6 categorical
     A +      AB +      O -      O -      A +      A + 

但是,乘积的类别是可以根据两个数组的类别创建的所有有序对组。因此,有些类别可能无法由输出数组的任何元素来表示。

categories(bloodTypes)
ans = 8×1 cell
    {'A +' }
    {'A -' }
    {'B +' }
    {'B -' }
    {'AB +'}
    {'AB -'}
    {'O +' }
    {'O -' }

局限性

  • 如果输入数组是数值、日期时间或持续时间数组,并且您根据输入中的值创建类别名称,则 categorical 会将它们舍入到五位有效数字。

    例如,categorical([1 1.23456789]) 根据这两个值创建类别名称 11.2346。要根据连续的数值、持续时间或日期时间数据创建类别,请使用 discretize 函数。

  • 如果输入数组的数值、日期时间或持续时间值间距过小,则 categorical 无法根据这些值创建类别名称。一般情况下,如果输入中任意两个值之间的差约小于 5e-5,则这些值的间距过小。

    例如,categorical([1 1.00001]) 无法根据这两个数值创建类别名称,因为它们之间的差太小。要根据连续的数值、持续时间或日期时间数据创建类别,请使用 discretize 函数。

提示

  • 有关接受或返回分类数组的函数列表,请参阅分类数组

扩展功能

全部展开

基于线程的环境
使用 MATLAB® backgroundPool 在后台运行代码或使用 Parallel Computing Toolbox™ ThreadPool 加快代码运行速度。

版本历史记录

在 R2013b 中推出