我使用 C 库在 R 中工作。我需要将一个数字在 1 到 10 之间的数组传递给 C 函数,但它也可以是“NA”。然后在 C 中,根据我需要设置输出的值。 这是一个简化的代码
heredyn.load("ranking.so")
fun <- function(ranking) {
nrak <- length(ranking)
out <- .C("ranking", as.integer(nrak), as.character(ranking), rr = as.integer(vector("integer",nrak)))
out$rr
}
ranking <- sample(c(NA,seq(1,10)),10,replace=TRUE)
rr <- fun(ranking)
C 函数可以简单地是这样的
#include <R.h>
void ranking(int *nrak, char *ranking, int *rr) {
int i ;
for (i=0;i<*nrak;i++) {
if (ranking[i] == 'NA')
rr[i] = 1 ;
else
rr[i] = (int) strtol(&ranking[i],(char **)NULL,10) ;
}
}
由于“NA”值,我将排名设置为字符,但也许还有另一种方法可以做到这一点,使用整数并且在调用函数之前不将“NA”替换为 0?
(像这样的代码,总是给我一个零数组...)
最佳答案
使用 R_NaInt
测试该值是否为 NA,例如
#include <R.h>
void ranking_c(int *nrak, int *ranking, int *rr) {
for (int i=0; i < *nrak; i++)
rr[i] = R_NaInt == ranking[i] ? -1 : ranking[i];
}
通过明确允许 NA 从 R 调用
> x = c(1:2, NA_integer_)
> .C("ranking_c", length(x), as.integer(x), integer(length(x)), NAOK=TRUE)[[3]]
[1] 1 2 -1
或者,使用 R 的 .Call()
接口(interface)。每个 R 对象都表示为一个 S 表达式。有 C 级函数来操作 S 表达式,例如长度 Rf_length()
、数据访问 INTEGER()
和分配 Rf_allocVector()
不同类型的 S 表达式,例如用于整数 vector 的 INTSXP。
R 内存管理使用垃圾收集器,它可以在任何分配内存的调用上运行。因此,最佳做法是 PROTECT()
在范围内的任何 R 分配。
您的函数将接受 0 个或多个 S 表达式作为输入,并返回单个 S 表达式;它可能被实现为
#include <Rinternals.h>
#include <R_ext/Arith.h>
SEXP ranking_call(SEXP ranking)
{
/* allocate space for result, PROTECTing from garbage collection */
SEXP result = PROTECT(Rf_allocVector(INTSXP, Rf_length(ranking)));
/* assign result */
for (int i = 0; i < Rf_length(ranking); ++i)
INTEGER(result)[i] =
R_NaInt == INTEGER(ranking)[i] ? -1 : INTEGER(ranking)[i];
UNPROTECT(1); /* no more need to protect */
return result;
}
并使用 .Call("ranking_call", as.integer(ranking))
从 R 调用。
使用 .Call
在速度和内存分配方面比 .C
更有效(.C 可能会在途中复制原子 vector ),但主要原因使用它是因为它在直接使用 R 的数据结构方面提供了灵 active 。当返回值比原子 vector 更复杂时,这一点尤其重要。
关于c - 使用 "NA"将 R 数组传递给 C 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35638599/