R作为一种通用编程语言

16 投票
3 回答
7654 浏览
提问于 2025-04-16 07:55

我之前喜欢Python,因为它有很多内置的数据类型,比如集合、字典、列表和元组。这些结构可以帮助我们写出简短的脚本来处理数据。

另一方面,R就像Matlab,它的数据类型有标量、向量、数据框、数组和列表。但它缺少集合、字典、元组等。我知道列表类型很强大,很多操作可以看作是列表处理。但是,把R当作一种通用编程语言的想法还是不太明确。

(以下只是一个例子,并不是说我专注于文本处理或挖掘。)

比如,我需要对一组新闻文章进行TF-IDF计数(假设有20万篇文章在一个文件夹及其子文件夹中)。

在读取文件后,我需要进行词到ID的映射和其他计数任务。这些任务涉及字符串操作,需要像集合或映射这样的容器。

我知道我可以用其他语言来处理这些,然后把数据加载到R中。但也许(对于小任务)把所有预处理放在一个R脚本中会更好。

所以我的问题是,R在语言层面上是否有足够的能力来处理这种丰富的数据结构?如果没有,有没有什么包可以为R语言提供很好的扩展?

3 个回答

3

你可以看看这个自然语言处理任务视图

主题标题:

语音学和语音处理:
词汇数据库:
关键词提取和一般字符串处理:
自然语言处理:
字符串核:
文本挖掘:

4

其实,R语言并不是没有集合、字典、列表和元组,只是它们以其他结构的形式存在。当然,性能可能会是个问题,但通常来说,它的表现并不比Python差,而且你通常可以找到一个用高效C语言编写的包来解决这个问题。

我对文本挖掘了解不多,不过可以看看tm这个包,里面可能有你需要的东西。

24

我觉得R语言在数据预处理方面的能力有了很大的提升——也就是从数据源提取数据到分析步骤之前的所有工作——在过去三年里(这是我使用R的时间)有了显著改善。我每天都在用Python,已经有七年左右了——它的文本处理能力非常出色——但我仍然毫不犹豫地会选择R来完成你提到的那种任务。

不过有几点需要注意。首先,我建议你仔细看看一些外部包,这些包可以帮助你完成你问题中的任务——特别是hash(类似Python的键值数据结构)和stringr(主要是对基础库中不太友好的字符串处理函数的封装)。

这两个包stringrhash都可以在CRAN上找到。

> library(hash)
> dx = hash(k1=453, k2=67, k3=913)
> dx$k1
  [1] 453
> dx = hash(keys=letters[1:5], values=1:5)
> dx
  <hash> containing 5 key-value pair(s).
   a : 1
   b : 2
   c : 3
   d : 4
   e : 5

> dx[a]
  <hash> containing 1 key-value pair(s).
  a : 1

> library(stringr)
> astring = 'onetwothree456seveneight'
> ptn = '[0-9]{3,}'
> a = str_extract_all(astring, ptn)
> a
  [[1]]
  [2] "456"

似乎有很多R用户的日常工作中,文本处理和文本分析占据了很大一部分——这可以从CRAN的自然语言处理任务视图看出来(这是大约20个这样的非正式领域包集合之一)。在这个任务视图中,有一个包tm,专门用于文本挖掘的功能。tm中包含了一些优化的函数,可以处理你问题中提到的任务。

此外,R还有很多优秀的包,可以在相对较大的数据集上进行交互式工作(比如,> 1 GB),通常不需要设置并行处理的基础设施(但如果有集群的话,当然可以利用)。在我看来,最令人印象深刻的就是耶鲁大学的Michael Kane和John Emerson开发的"大内存项目"(CRAN)下的一系列包;这个项目包括bigmemory、biganalytics、synchronicity、bigtabulate和bigalgebra。总的来说,这些包背后的技术包括:(i) 将数据分配到共享内存,这样可以让不同的并发进程协调访问同一份数据;(ii) 文件支持的数据结构(我认为这和内存映射文件结构是同义的),可以通过指针快速从磁盘访问数据,从而避免了RAM对文件大小的限制。

不过,R的标准库中还有很多函数和数据结构,使得在接近普通RAM限制的数据上进行交互式工作变得更容易。例如,.RData是一种原生的二进制格式,使用起来非常简单(命令是saveload),而且压缩效果很好:

> library(ElemStatLearn)
> data(spam)
> format(object.size(spam), big.mark=',')
  [1] "2,344,384" # a 2.34 MB data file
> save(spam, file='test.RData')

这个文件'test.RData'只有176 KB,压缩比超过10倍

撰写回答