罗兰谈MATLAB的艺术

将想法转化为MATLAB

请注意

罗兰谈MATLAB的艺术已退役,不会更新。

在MATLAB中使用文本

我想介绍一下今天的客座博主Dave Bergstein,他是MathWorks的MATLAB产品经理。在今天的文章中,Dave讨论了MATLAB文本处理的最新更新。

内容

在今天的帖子中,我分享了一个使用new的文本处理示例字符串数组并收集新的文本操作函数,均在R2016b中引入。我也给出了最佳使用时间的建议字符串字符,或细胞为文本和分享一些我们对未来的想法。

也一定要看看Toshi的帖子字符串数组介绍和罗兰的帖子《弦乐之歌

例子:我的公交车晚点了多久?

我在纽约的朋友谈到了她的公交路线上的延误。让我们看看一些数据,看看火车和公共汽车有什么典型的延误。的开放纽约计划共享数据,其中包括6年来超过15万起公共交通事件。我从以下网站下载了此数据作为CSV文件:https://data.ny.gov/Transportation/511-NY-MTA-Events-Beginning-2010/i8wu-pqzv

导入数据

我把数据读入一个表使用readtable并指定TextType名值对为字符串将文本作为字符串数组读取。

数据=可读数据(511 _ny_mta_events__beginning_2010.csv“TextType”“字符串”);
警告:变量名已被修改为有效的MATLAB标识符。原始名称保存在VariableDescriptions属性中。

下面是表格中的变量列表:

data.Properties.VariableNames
ans = 1×13单元格数组第1至4列“EventType”“OrganizationName”“FacilityName”“Direction”第5至9列“City”“County”“State”“CreateTime”“CloseTime”第10至13列“EventDescription”“RespondingOrganiz…”“Latitude”“Longitude”

数据。EventDescription包含事件描述的字符串数组。让我们来仔细看看这些事件。

eventsStr = data.EventDescription;

与字符向量或字符向量的单元格数组不同,字符串数组的每个元素本身都是字符串。看看我如何索引字符串数组就像索引数字数组一样,然后取回字符串数组。

eventsStr (1:3)
ans = 3×1字符串数组"MTA NYC公交:由于早些时候的洪水Q11进入汉密尔顿海滩,正常服务恢复" "MTA NYC公交:由于施工,北行M1公交147街区域:Adam Clayton Powell Junior" "MTA NYC公交:由于延误,布朗克斯开往2号线和3号线在内文斯街站(布鲁克林)"

许多事件描述报告了诸如“运行晚10分钟”之类的延迟。例如,在事件5180中如何报告26分钟的延迟。

eventsStr (5180)
MTA长岛铁路:由于轨道上有碎片,蒙托克站(萨福克县)和牙买加站(皇后区)之间的蒙托克分支向西行驶,上午6:44从蒙托克出发,9点32分到达牙买加,由于汉普顿湾附近的轨道上有一辆未经授权的车辆,晚点了26分钟。

确定延迟

我想找到所有包含' late '的事件。MATLAB R2016b还引入了十几个处理文本的新函数。这些函数使用字符向量、字符向量的单元格数组和字符串数组。您可以从。中了解这些函数字符和字符串页在我们的文档。

我将文本转换为所有小写字母,并确定哪些事件包含' late '使用包含函数。

eventsStr = lower(eventsStr);idx = contains(eventsStr,“晚”);lateEvents = eventsStr(idx)

提取延迟时间

我使用这些函数从“晚了10分钟”这样的短语中提取出迟到的分钟数extractAfter而且extractBefore

让我们来看看第一个后期事件。我们正在寻找的确切短语没有出现在这个事件中。当我们查找'operating'后面的文本时,会返回a失踪字符串。

lateEvents (1) extractAfter (lateEvents (1),“操作”
mta长岛铁路:由于延误,在spek站(spek)和纽约Penn站(manhattan)之间的西行巴比伦支线于早上5:08在纽约7:02出发,在巴比伦晚了15分钟

让我们来看看第二个后期事件。此字符串包含短语'operating 14 minutes late'。在“操作”后提取文本,我们得到“由于信号问题而晚了14分钟”。在'minutes late'之前提取文本,我们得到' 14 ',我们可以使用它将其转换为数值

lateEvents(2) s = extractAfter(lateEvents(2),“操作”) s = extractBefore(s,“分钟”minLate = double(s)
ans = "mta长岛铁路:由于延误bethpage站(萨福克县)西行的ronkonkoma支线,上午8:01到达宾州站的列车由于信号问题晚点14分钟s = "信号问题晚点14分钟" s = " 14 " minLate = 14

成功!我们从事件描述中提取了火车延误。现在让我们把这些放在一起。方法从所有事件中提取迟到的分钟数,并删除缺失的值rmmissing函数。然后将剩余的值转换为使用的数字并绘制结果的直方图。

s = extractAfter(lateEvents,“操作”);s = extractBefore(s,“分钟”);S = rmmissing(S);minLate = double(s);直方图(minLate 0:5:40) ylabel (“事件数量”)包含(“分钟”)标题({交通延误的“纽约大都会运输管理局”})

看起来报告的延误通常是10-15分钟。这个简单的例程捕获了许多运输延误,但不是全部。这种模式并不总是合适的(再考虑一下lateEvents (1)).我还忽略了可能以小时为单位报告的任何延迟。你能改进吗?

文本作为数据

字符串数组是类似上面例子的文本数据的一个很好的选择,因为它们具有内存效率,并且比字符向量的单元格数组(以前称为cellstr).

让我们比较一下内存使用情况。函数将字符串数组转换为字符向量的单元格数组cellstr命令并检查内存.参见Bytes列-它显示字符串数组的效率大约高出12%。

eventsCell = cellstr(eventsStr);谁事件*
名称大小字节类属性eventsCell 151225x1 73208886 cell eventsStr 151225x1 64662486 string

对于许多较小的文本,节省的内存要大得多。例如,假设我想将每个单词存储为一个单独的数组元素。方法将所有150,000个报表连接到一个长字符串中加入函数。然后,使用空格分隔这个长字符串分裂函数。结果是一个字符串数组,在单独的元素中存储超过400万个单词。这里内存节省了近2倍。

wordsStr = split(join(eventsStr));wordsCell = split(join(eventsCell));谁字*
名称大小字节类属性wordsCell 4356256x1 535429652 cell wordsStr 4356256x1 284537656 string

字符串数组的性能也更好。您可以将字符串数组与R2016b中引入的文本操作函数结合使用,从而获得最佳性能。这里我比较一下性能取代的字符串数组strrep在字符向量的单元格数组上。看看取代使用字符串数组的速度大约是strrep用单元格数组。

f1 = @() replace(eventsStr,“延迟”“晚了”);f2 = @() strrep(eventsCell,“延迟”“晚了”);时间(f1)时间(f2)
Ans = 0.062507 Ans = 0.23239

文本类型建议

所有文本都应该使用字符串数组吗?也许还没有。MATLAB有三种不同的方式来存储文本:

  • 字符向量(字符
  • 字符串数组(字符串
  • 字符向量的单元格数组(细胞

目前(从R2017a开始),我们鼓励您使用字符串数组来存储文本数据,比如传输事件。我们不建议在其他地方使用字符串数组,因为字符串数组在MATLAB中还不是到处都被接受。注意我是如何使用字符向量来指定文件名的readtable以及图形标题的字符向量单元格数组。

展望未来

将来呢?我们认为字符串数组比字符向量和字符向量的单元格数组提供了更好的体验。我们的计划是随着时间的推移推出更广泛的字符串数组使用。

在接下来的几个版本中,我们将更新更多的MATLAB函数和属性,以接受字符向量和字符向量的单元格数组之外的字符串数组。当我们这样做时,在更多的地方使用字符串数组将变得更容易。

接下来,我们将用字符串数组替换MATLAB中的字符向量的单元格数组。注意,单元格数组本身不会去任何地方。它们是一种重要的MATLAB容器类型,适合用于存储混合数据类型或锯齿大小的数组。但我们预计它们在文本数据中的使用将会减少,并在很大程度上被字符串数组所取代,字符串数组具有更高的内存效率,并且对纯文本数据表现更好。

除此之外,随着时间的推移,我们将在新函数和新属性中使用字符串数组来代替字符向量(但为了兼容性,将在许多地方继续返回字符向量)。我们预计字符向量将继续存在于版本到版本的代码兼容性和特殊用例中。

说到兼容性:我们非常关心MATLAB代码的版本到版本的兼容性,今天比以往任何时候都更加关心。因此,我们在滚出字符串数组时执行以下步骤:

  1. 文本操作函数(包括旧的和新的)返回传递给它们的文本类型。这意味着您可以选择在这些函数中使用字符串(不需要使用字符串)。注意我是如何使用分裂而且加入上面的字符串数组或单元格数组的字符向量。
  2. 今天我们推荐字符串数组用于文本数据应用程序。这里有一些方法可以选择使用字符串。在本例中,我选择从中获取字符串数组readtable使用TextType名称-值对。字符串数组从函数返回extractBefore因为我传递了一个字符串数组作为输入。
  3. 为了兼容,我们为字符串数组添加了花括号索引,返回一个字符向量。当你用花括号建立索引时,单元格数组返回它们的内容{}.使用字符向量单元格数组的代码通常用花括号索引数组以访问字符向量。这样的代码可以用于字符串数组,因为花括号索引也将返回字符向量。看看下面的代码如何返回相同的结果f单元格数组或字符串:
D =日期时间(“现在”);F = {“h”“米”“年代”};%使用单元格数组n = 1:3, d.Format = f{n};disp (d)结束
9 43 10
F = [“h”“m”“s”];%使用字符串数组n = 1:3, d.Format = f{n};disp (d)结束
9 43 10

期待从我这里听到更多关于这个话题的信息。请在下方留言与我们分享你的想法。我们有兴趣听到你的声音

我们希望字符串数组将帮助您实现您的目标,并且我们正在采取的步骤将使您顺利采用。如果您还没有尝试过字符串数组,请从我们的文档中了解更多字符和字符串




发布与MATLAB®R2017a

|