首先我要说的是,我孜孜不倦地避免使用手工清理数据来支持正则表达式等.但是,偶尔也是不可避免的.
我通常使用类似Load-Clean-Func-Do工作流程的东西,所以这显然适合清洁阶段.但是,如果需要更新,任何手动编辑都会破坏在手动清洁之前运行这些东西的能力.
我能想到至少有三种方法可以解决这个问题:
2的问题在于它可能非常不合适.3的问题是我不知道任何这样的工具存在于R. Stata有一个非常好的实现.
所以问题是:
现在是lambda演算的一个众所周知的定理,任何带有两个或多个参数的函数都可以通过currying作为一个带有一个参数的函数链来编写:
# Pseudo-code for currying
f(x,y) -> f_curried(x)(y)
Run Code Online (Sandbox Code Playgroud)
事实证明,这不仅在研究函数的行为方面,而且在实际应用中都非常强大(Haskell等).
但是,似乎没有讨论返回值的函数.程序员通常通过返回一些元对象(R中的列表,C++中的结构等)来处理它们无法从函数返回多个值.它总是让我觉得有点像一个kludge,但它是一个有用的.
例如:
# R code for "faking" multiple return values
uselessFunc <- function(dat) {
model1 <- lm( y ~ x , data=dat )
return( list( coef=coef(model1), form=formula(model1) ) )
}
Run Code Online (Sandbox Code Playgroud)
问题
如何编写一个足够灵活的主函数来将额外的参数传递给多个函数?简单的尝试失败了:
> mainF <- function(f1,f2,...) {
+ f2( X=f1(...), ... )
+ }
> mainF(function(x) x, function(X, y) X*y, x=5, y=3)
Error in f2(X = f1(...), ...) : unused argument (x = 5)
Run Code Online (Sandbox Code Playgroud)
通过检查形式并将省略号中的调用参数与每个函数的形式匹配,我可以看到这是如何可行的.但是有更好的方法吗?
我最近被指向Roxygen解决我的文档困境/懒惰.但是在这个闪亮的Roxygen2中,根据我的理解,它有点像它自己的东西.Hadley的包装工具需要使用Roxygen2,但在任何地方都没有通过走路的方式.
鉴于我在学习过程中从头开始:
是否有一个用户,对于新用户,有利于Roxygen而不是Roxygen2,或者Roxygen2在所有方面都更好?
如果有的话,有哪些资源用于学习(最好是那些不依赖于Roxygen先前知识的资源)?
Roxygen2是否与Roxygen向后兼容(这样投入学习和写作Roxygen的时间会延续下去)?
我在学习R时写了一个包,它的依赖列表很长.我试图削减它,因为两种情况:
是否有自动跟踪这两种情况的方法?我可以想到两个粗略的方法(下载所有依赖包中的函数列表,并通过我的包的代码自动进行文本搜索,或者加载包函数而不加载所需的包并执行直到出现错误),但是都没有看起来特别优雅或万无一失......
这个问题可能会或可能不会受到我失去整个3小时地理编码运行的启发,因为其中一个值返回了错误.提示怜悯(下)投票.
基本上在被调用的函数内返回了一个错误sapply.我曾经options(error=recover),但尽管浏览了我可以使用的每个级别,我找不到任何将(数千次成功)调用FUN的结果存储在内存中的地方.
我在浏览周围时发现的一些对象在我尝试检查它们时会出错,声称引用不再有效.不幸的是我丢失了特定的错误消息.
这是一个快速的例子,虽然它没有复制引用错误(我怀疑它与消失的环境有关并且可能并不重要),但它确实证明我看不到保存已处理数据的方法.
有这样的技术吗?
请注意,我已经意识到我的错误并插入了比之前存在的更强大的错误处理try,但我正在寻找一种方法来事后恢复内容而不是事前.
测试功能
sapply( seq(10), function(x) {
if(x==5) stop("Error!")
return( "important data" )
} )
Run Code Online (Sandbox Code Playgroud)
互动探索
> sapply( seq(10), function(x) {
+ if(x==5) stop("Error!")
+ return( "important data" )
+ } )
Error in FUN(1:10[[5L]], ...) : Error!
Enter a frame number, or 0 to exit
1: sapply(seq(10), function(x) {
if (x == 5)
stop("Error!")
return("important data")
})
2: lapply(X = X, FUN = FUN, ...)
3: FUN(1:10[[5]], …Run Code Online (Sandbox Code Playgroud) 构建包会导致以下警告:
* checking for unstated dependencies in tests ... WARNING
‘library’ or ‘require’ call not declared from: ‘testthat’
* checking tests ...
Running ‘test-all.R’
OK
* checking PDF version of manual ... OK
WARNING: There was 1 warning.
Run Code Online (Sandbox Code Playgroud)
包目录有一个名为的文件夹tests,文件为test-all.R:
library(testthat)
library(bootLR)
test_package("bootLR")
Run Code Online (Sandbox Code Playgroud)
然后是一个子文件夹,里面testthat有两个文件,用于存放各种测试.
错误消息可能告诉我,我没有在DESCRIPTION文件中声明testthat,但我不想要求最终用户安装它,我相信将该library(testthat)语句放在test-all.R文件中来自测试手册.
任何方式,或者我必须以正确的方式添加它(强制用于安装testthat)?
编辑:我想添加它Suggests:可能是最好的方法吗?
我Rcpp用来包装一个用C语言编写的算法(不是我)(没有STL,没有提升,没有任何东西,据我所知).你可以在这里看到实现的算法(我正在包装kmeans_w_03).因此,我numeric从R 传入一个向量,然后需要将其转换为double数组.
目前我正在逐个元素地循环并从"tother"中填充一个,如下所示:
SEXP testfn(SEXP weightvec, SEXP cluster_num_k){
Rcpp::NumericVector weightR(weightvec) ;
int point_num = weightR.size();
double weight[point_num] ;
for(int i = 0; i < point_num; ++i) {
weight[i] = weightR[i];
}
}
Run Code Online (Sandbox Code Playgroud)
但是使用单元素数字向量,我可以利用Rcpp的漂亮的as转换功能:
int cluster_num = Rcpp::as<int>(cluster_num_k);
Run Code Online (Sandbox Code Playgroud)
但是,为长度> 1的数字向量尝试类似的东西会导致崩溃或错误,具体取决于语法的确切变体:
double weight[point_num] = Rcpp::as<double>(weightvec);
Run Code Online (Sandbox Code Playgroud)
我不一定介意循环,但我是一个完全新手,并怀疑有更好的方法.我已经阅读了Rcpp介绍,hadley的wiki教程和RcppExamples,但还没有找到解决这个问题的任何内容,但这并不意味着我不会错过它.我读到的Doxygen Rcpp文档是as可以转换为STL向量而不是数组(但我很难读取这些文档,所以我怀疑我错了).如果是这样,我想我可以投射到一个向量,然后到一个数组....
所以我的问题是:是否有更好的(更少的代码行,更具表现力的代码,甚至可以避免内存分配)的方式将a转换NumericVector为double[]?
我一直在努力,我想知道是否有一个简单的解决方法.对于某些情况,我发现考虑对矩阵进行子集化更合乎逻辑
N <- 12
N.NA <- 6
dat <- data.frame(V1=runif(N),V2=runif(N))
sel.mat <- matrix(c(sample(seq(N),N.NA),sample(ncol(dat),N.NA,replace=TRUE)),ncol=2)
Run Code Online (Sandbox Code Playgroud)
这适用于选择,但不适用于替换:
> dat[sel.mat]
[1] 0.2582569 0.8455966 0.8828083 0.5384263 0.9574810 0.5623158
> dat[sel.mat] <- NA
Error in `[<-.data.frame`(`*tmp*`, sel.mat, value = NA) :
only logical matrix subscripts are allowed in replacement
Run Code Online (Sandbox Code Playgroud)
我意识到错误消息是有原因的(如果你有多个替换指向同一个元素,它就不知道该怎么办),但这并不能阻止R允许对矢量进行整数替换(例如dat$V1[c(2,3)] <- NA).
有没有一种方便的方法允许用整数矩阵替换?
我正在尝试使用doParallel和foreach包,但是我使用此处CRANpage中的指南中的bootstrapping示例来降低性能.
library(doParallel)
library(foreach)
registerDoParallel(3)
x <- iris[which(iris[,5] != "setosa"), c(1,5)]
trials <- 10000
ptime <- system.time({
r <- foreach(icount(trials), .combine=cbind) %dopar% {
ind <- sample(100, 100, replace=TRUE)
result1 <- glm(x[ind,2]~x[ind,1], family=binomial(logit))
coefficients(result1)
}
})[3]
ptime
Run Code Online (Sandbox Code Playgroud)
此示例返回56.87.
当我将doparto 更改为仅do按顺序而不是并行运行时,它将返回36.65.
如果我这样做registerDoParallel(6)会将并行时间缩短到42.11但仍然比顺序慢. registerDoParallel(8)变得40.31比连续更糟糕.
如果我增加到trials100,000,那么顺序运行需要417.16和3个工作程序的并行运行597.31.它需要6名工人425.85.
我的系统是
戴尔Optiplex 990
Windows 7专业版64位
16GB RAM
英特尔i-7-2600 3.6GHz四核,具有超线程功能
我在这里做错了吗?如果我做了我能想到的最人为的事情(用计算代码替换Sys.sleep(1)),那么我得到的实际减少量与工人数量成正比.我想知道为什么指南中的例子会降低我的表现,而对他们来说它会加快速度?
r ×10
c++ ×1
dependencies ×1
mpi ×1
package ×1
packages ×1
rcpp ×1
return-value ×1
roxygen ×1
roxygen2 ×1