如果给一个对象x
,是有办法分类它是否是S3
或S4
(或"其他")?我已经看过is.object()
并isS4()
,并可以识别的东西是一个对象(或没有),而且它是一个S4对象(或没有).但是,在我看来,S3对象并不是所有不是S4对象的对象的补充.
因此,如何以编程方式完成这些任务?
这是一个让我烦恼的例子,取自以下的帮助is.object()
:
a = as.factor(1:3)
is.object(a) # TRUE
isS4(a) # FALSE
Run Code Online (Sandbox Code Playgroud)
这是否意味着这a
是一个S3
对象?
我原以为R有一个标准的开销用于存储对象(24个字节,似乎,至少对于整数向量),但一个简单的测试显示它比我意识到的更复杂.例如,采用长度为100的整数向量(使用随机抽样,希望避免任何可能存在的偷偷摸摸的序列压缩技巧),我发现不同长度的向量可以具有相同的大小,如下所示:
> N = 100
> V = vector(length = 100)
> for(L in 1:N){
+ z = sample(N, L, replace = TRUE)
+ V[L] = object.size(z)
+ }
>
> options('width'=88)
> V
[1] 48 48 56 56 72 72 72 72 88 88 88 88 104 104 104 104 168 168 168 168
[21] 168 168 168 168 168 168 168 168 168 168 168 168 176 176 184 184 192 192 200 200
[41] 208 …
Run Code Online (Sandbox Code Playgroud) 我正在尝试优化一些代码,并对来自的信息感到困惑summaryRprof()
.特别是,它看起来像是对外部C程序进行了多次调用,但是我无法确定哪个 C程序,从哪个R函数.我打算通过一堆切片和切割代码来解决这个问题,但是想知道我是否忽略了一些更好的方法来解释分析数据.
消耗最多的函数.Call
,显然是对C代码调用的一般描述; 下一个主要功能似乎是赋值操作:
$by.self
self.time self.pct total.time total.pct
".Call" 2281.0 54.40 2312.0 55.14
"[.data.frame" 145.0 3.46 218.5 5.21
"initialize" 123.5 2.95 217.5 5.19
"$<-.data.frame" 121.5 2.90 121.5 2.90
"as.vector" 110.5 2.64 416.0 9.92
Run Code Online (Sandbox Code Playgroud)
我决定专注于.Call
看看它是如何产生的.我查看了分析文件以查找.Call
调用堆栈中的条目,以下是调用堆栈中的顶部条目(按出现次数计算):
13640 "eval"
11252 "["
7044 "standardGeneric"
4691 "<Anonymous>"
4658 "tryCatch"
4654 "tryCatchList"
4652 "tryCatchOne"
4648 "doTryCatch"
Run Code Online (Sandbox Code Playgroud)
这个清单就像泥巴一样清晰:我有<Anonymous>
和standardGeneric
在那里.
我相信这是由于调用Matrix包中的函数,但那是因为我正在查看代码,并且该包似乎是唯一可能的C代码源.但是,在这个包中调用了Matrix的许多不同的函数,并且这次确定哪个函数正在消耗似乎非常困难.
所以,我的问题是非常基本的:有破译和归因这些调用(例如某种方式.Call
,<Anonymous>
在一些其他的方式,等等)?考虑到所涉及的函数数量,此代码的调用图的绘图相当棘手.
我看到的后备策略要么是(1)注释掉一些代码(以及为了使代码能够工作而破解)以查看时间消耗发生的位置,或者(2)将某些操作包装在其他函数中并查看当这些函数出现在调用堆栈上时.后者是不优雅的,但似乎这是向调用堆栈添加标记的最佳方式.前者是令人不愉快的,因为运行代码需要相当长的时间,迭代地取消注释代码并重新运行是令人不快的.
虽然一样的工具RUnit
,svUnit
以及testthat
有利于开发包,我认为这将是非常有用的上传测试脚本或特定包装甚至只是用法示例的一些手段.持续集成(例如Jenkins)甚至基本单元测试的用户可能已经有过这样的测试,并且发现为包维护者的使用贡献脚本是有益的.
这些功能是通过CRAN还是RForge存在,还是通过其他站点(例如github)存在?如果是这样,是否有一个使用存储库的主要示例,例如github,以允许用户提供测试?
(感谢@mariotomo提醒我svUnit
.)
我有一些工作流程,我希望R在完成脚本后暂停运行的Linux机器.我可以想到两种类似的方法来做到这一点:
system("halt")
halt
在R位完成后运行shell脚本.还有其他简单的方法吗?
这里的用例是针对在AWS上运行的脚本,我希望在脚本完成后实例停止,这样我就不会在作业运行后收取机器时间的费用.我用于数据分析的实例是一个EBS支持的实例,因此我不想终止它,只需暂停.从实例内部发出halt命令与从AWS控制台停止/挂起的效果相同.
在R控制台中工作时,我想设置监视特定连接的后台任务,当事件发生时,执行另一个功能(警报).或者,我可以进行设置,以便外部函数只是向R发送警报,但这似乎是同样的问题:有必要设置一个监听器.
我可以在R的专用过程中执行此操作,但我不知道在控制台中是否可行.另外,如果它正在计算一个函数,我对中断R不感兴趣,但是如果控制台只是在等待输入,则警告或中断.
以下是三个用例:
最简单的例子是观看文件.假设我有一个名为"latestData.csv"的文件,我想监视它的变化; 当它改变时,myAlert()
执行.(可以将它扩展为执行不同的操作,但只是弹出一个文件已更改的注释是有用的.)
一种不同类型的监视器将监视给定的机器是否在RAM上运行不足并且可能执行save.image()
并终止.同样,这可能是一个简单的问题,即观察由外部监视器生成的文件,该文件可以保存输出top
或其他命令.
一个不同的例子就像另一个最近的SO问题,关于:让R停止正在运行的EC2机器.如果来自另一台机器或进程的警报告诉程序保存并终止,那么能够监听该警报将是很好的.
目前,我怀疑有两种方法可以解决这个问题:通过Rserve和可能的via fork
.如果有人有关于如何使用包或通过其他方法执行此操作的示例,那将是很好的.我认为解决这三个用例中的任何一个都可以解决所有这些问题,模拟一些外部代码.
注1:我意识到,根据另一个SO问题的答案,R是单线程的,这就是我怀疑fork
和Rserve可能工作的原因.但是,如果一个人与R终端接口,我不确定可行性.虽然R的REPL附加到控制台的输入,但我试图绕过它或模仿它,这是答案的地方fork
或Rserve
可能.
注2:对于那些熟悉事件处理/事件处理方法的人来说,这也可以解决所有问题.我在R中找不到任何相关内容.
更新1:我发现编写R扩展的手册有一个引用事件处理的部分,其中提到了使用R_PolledEvents
.这很有希望.
我已经查看了帮助update.packages(..., checkBuilt = TRUE)
,我不明白为什么人们不希望TRUE
作为默认值.默认是FALSE
.
这个问题有两个部分.(1)有人可以给使用这种说法和理由的任一个明确的解释FALSE
或TRUE
?
据我所知,如果一个更新R,那么这可能有不同的结果 - 如果包没有更新,那么FALSE
不会导致本地库被更新的包修改,同时TRUE
将导致更多(所有?)包得到更新.默认选项(FALSE
)可以提供速度优势 - 更新的包将更少.稳定性是不确定的 - 新版本的R可能在新软件包中运行得更好,或者可能没有(例如,如果新软件包中存在回归/错误),并且它可能适用于或不适用于早期版本的软件包(不保证向后兼容性).其他利弊对我来说并不明显.(我可能在这里错了 - 这就是为什么我要求澄清作为第1部分.)
(2)但是,如果没有更改R的安装版本,那么这些结果是否应该相同?看一下这个帖子的例子似乎只是调用已update.packages()
创建的问题,即使R的版本没有改变.
我曾经遇到过这个问题几次,并且我无法弄清楚任何解决方案,只能解决这个问题(见下文).
假设一台计算机正在运行2个以上的R实例,由于2个用户或1个用户正在运行多个进程,并且有一个实例在执行update.packages()
.我有好几次,其他的实例可能会被大肆污染.正在更新的软件包不会以任何影响计算的方式更改功能,但不知何故会出现一个大问题.
简单的解决方案(解决方案0)是在update.packages()
执行时终止R的所有实例.这有2个问题.首先,必须终止R实例.其次,人们甚至无法确定这些实例的运行位置(请参阅更新1).
假设正在执行的代码的行为不会改变(例如,包更新都是有益的 - 它们只修复错误,提高速度,减少RAM,并授予独角兽),是否有某种方法可以热插拔新版本的包对其他流程的影响较小?
在R之外我还有两个候选解决方案:
解决方案1是使用临时库路径,然后删除旧的旧库并将新库移动到其位置.这样做的缺点是删除+移动可能会产生一些时间,在此期间没有任何可用的东西.
解决方案2是使用符号链接指向库(或库层次结构),并使用指向更新包所在的新库的指针覆盖符号链接.这似乎导致更少的软件包停机时间 - 操作系统覆盖符号链接所需的时间.这样做的缺点是它在管理符号链接时需要更多的关注,并且是特定于平台的.
我怀疑解决方案#1可以通过巧妙的使用来修改为#2,.libPaths()
但这似乎不需要调用update.packages()
,而是编写一个新的更新程序,找到过时的包,将它们安装到临时库,然后更新库路径.这样做的好处是,可以将现有流程约束到.libPaths()
它启动时的流程(即更改R知道的库路径可能不会传播到那些已经运行的实例,而不在该实例中进行一些明确的干预).
更新1.在示例方案中,两个竞争R实例位于同一台计算机上.这不是必需的:据我了解更新,如果两者共享相同的库,即共享驱动器上的相同目录,则更新仍然可能导致问题,即使R的另一个实例在另一台机器上.因此,人们可能会意外地杀死R进程,甚至看不到它.
在我的python环境中,已经安装了Rpy和Scipy包.
我想解决的问题是这样的:
1)大量财务数据存储在文本文件中.无法加载到Excel
2)我需要总结某些字段并得到总数.
3)我需要根据总数显示前10行.
哪个包(Scipy或Rpy)最适合此任务?
如果是这样,你能否提供一些可以帮助我实施解决方案的指针(例如文档或在线示例)?
速度是一个问题.理想情况下scipy和Rpy可以处理大文件,即使文件太大而无法安装到内存中
我有两个大的数据帧,a
并b
为这identical(a,b)
是TRUE
按原样all.equal(a,b)
,不过identical(digest(a),digest(b))
是FALSE
.什么可能导致这个?
更重要的是,我试图通过将摘要应用于一堆行来深入挖掘.令人难以置信的是,至少在我看来,子帧的摘要值一直到数据帧的最后一行是一致的.
这是一系列比较:
> identical(a, b)
[1] TRUE
> all.equal(a, b)
[1] TRUE
> digest(a)
[1] "cac56b06078733b6fb520442e5482684"
> digest(b)
[1] "fdd5ab78ca961982d195f800e3cf60af"
> digest(a[1:nrow(a),])
[1] "e44f906723405756509a6b17b5949d1a"
> digest(b[1:nrow(b),])
[1] "e44f906723405756509a6b17b5949d1a"
Run Code Online (Sandbox Code Playgroud)
我能想到的每个方法都表明这两个对象是相同的,但它们的摘要值是不同的.数据框还有其他可以产生这种差异的东西吗?
有关详细信息:对象大约是10M行x12列.这是输出str()
:
'data.frame': 10056987 obs. of 12 variables:
$ V1 : num 1 11 21 31 41 61 71 81 91 101 ...
$ V2 : num 1 1 1 1 1 1 1 1 …
Run Code Online (Sandbox Code Playgroud)