如何在 R 中矢量化此 is_prime 函数?
How do I vectorize this is_prime function in R?
我创建了这个函数,它接受数字和 return TRUE 或 FALSE,具体取决于数字是否为质数。
is.prime <- function(num) {
if (num == 2) {
TRUE
} else if (any(num %% 2:(num-1) == 0)) {
FALSE
} else {
TRUE
}
}
然而,这个函数只接受一个值,例如这个工作正常:
> is_prime(17)
[1] TRUE
如果我插入一个向量,我想查看每个元素的 TRUE 或 FALSE。例如,
> is_prime(c(17,5,10,22,109,55))
[1] TRUE
Warning messages:
1: In if (x == 1) { :
the condition has length > 1 and only the first element will be used
2: In 2:(floor(x/2)) :
numerical expression has 6 elements: only the first used
3: In x%%2:(floor(x/2)) :
longer object length is not a multiple of shorter object length
这是针对第一个元素求值的,但我想看看
TRUE TRUE FALSE FALSE TRUE FALSE
为矢量
is_prime(c(17,5,10,22,109,55))
我如何修改函数以使用相同的算法进行矢量化?
从技术上讲,您不能向量化函数,但可以使用方法将 is.prime
函数应用于向量。
例如,使用sapply
:
sapply(c(17,5,10,22,109,55), is.prime)
#[1] TRUE TRUE FALSE FALSE TRUE FALSE
或者使用 Vectorize
,它是 mapply
的包装器:
vec.is.prime <- Vectorize(is.prime)
vec.is.prime(c(17,5,10,22,109,55))
#[1] TRUE TRUE FALSE FALSE TRUE FALSE
半矢量化
可以通过以矢量化方式处理偶数(和其他一些数字)来矢量化某些函数。其余的由 vapply
.
处理
helper <- function(x) {
for (k in seq(3, round(sqrt(x)) + 1, 2)) {
if (x %% k == 0)
return(FALSE)
}
return(TRUE)
}
is.prime <- function(v) {
out <- rep(TRUE, length(v))
out[v %% 2 == 0 | v %in% c(1)] <- FALSE
out[v %in% c(2, 3, 5)] <- TRUE
indices <- which(v > 5 && v == FALSE)
out[indices] <- vapply(v[indices], helper, logical(1))
return(out)
}
is.prime(c(17,5,10,22,109,55))
# [1] TRUE TRUE FALSE FALSE TRUE FALSE
全矢量化
如果性能受到威胁,您可以考虑使用 `Rcpp`:
c++文件
#include <Rcpp.h>
#include <math.h>
using namespace Rcpp;
bool is_prime(int n) {
if ((n == 2) || (n == 3) || (n == 5)) {
return true;
}
if ((n % 2 == 0) || (n == 1)) {
return false;
}
int i = 3;
while (i < round(sqrt(n)) + 1) {
if (n % i == 0) {
return false;
}
i += 2;
}
return true;
}
// [[Rcpp::export]]
LogicalVector is_prime(IntegerVector v) {
int n = v.length();
LogicalVector out = LogicalVector(n);
for (int i = 0; i < n; i++) {
out[i] = is_prime(v[i]);
}
return out;
}
R 文件
library(Rcpp)
sourceCpp('prime_fun.cpp') # if cpp file in same dir
is_prime(c(17,5,10,22,109,55))
# [1] TRUE TRUE FALSE FALSE TRUE FALSE
R 本质上是一种矢量化语言,您只需在编写函数时不要破坏它...
is.prime <- function(num){
res<-rep(TRUE, length(num))
for(i in 2:(max(num)-1) ){
res[(i < num) & ((num %% i) == 0) ] <- FALSE
}
return(res)
}
x<-c(2, 5, 17, 109, 10, 22, 55, 93)
print("Primes:")
print(x[ is.prime(x) ] )
输出:
> source('~/.active-rstudio-document')
[1] "Primes:"
[1] 2 5 17 109
我创建了这个函数,它接受数字和 return TRUE 或 FALSE,具体取决于数字是否为质数。
is.prime <- function(num) {
if (num == 2) {
TRUE
} else if (any(num %% 2:(num-1) == 0)) {
FALSE
} else {
TRUE
}
}
然而,这个函数只接受一个值,例如这个工作正常:
> is_prime(17)
[1] TRUE
如果我插入一个向量,我想查看每个元素的 TRUE 或 FALSE。例如,
> is_prime(c(17,5,10,22,109,55))
[1] TRUE
Warning messages:
1: In if (x == 1) { :
the condition has length > 1 and only the first element will be used
2: In 2:(floor(x/2)) :
numerical expression has 6 elements: only the first used
3: In x%%2:(floor(x/2)) :
longer object length is not a multiple of shorter object length
这是针对第一个元素求值的,但我想看看
TRUE TRUE FALSE FALSE TRUE FALSE
为矢量
is_prime(c(17,5,10,22,109,55))
我如何修改函数以使用相同的算法进行矢量化?
从技术上讲,您不能向量化函数,但可以使用方法将 is.prime
函数应用于向量。
例如,使用sapply
:
sapply(c(17,5,10,22,109,55), is.prime)
#[1] TRUE TRUE FALSE FALSE TRUE FALSE
或者使用 Vectorize
,它是 mapply
的包装器:
vec.is.prime <- Vectorize(is.prime)
vec.is.prime(c(17,5,10,22,109,55))
#[1] TRUE TRUE FALSE FALSE TRUE FALSE
半矢量化
可以通过以矢量化方式处理偶数(和其他一些数字)来矢量化某些函数。其余的由 vapply
.
helper <- function(x) {
for (k in seq(3, round(sqrt(x)) + 1, 2)) {
if (x %% k == 0)
return(FALSE)
}
return(TRUE)
}
is.prime <- function(v) {
out <- rep(TRUE, length(v))
out[v %% 2 == 0 | v %in% c(1)] <- FALSE
out[v %in% c(2, 3, 5)] <- TRUE
indices <- which(v > 5 && v == FALSE)
out[indices] <- vapply(v[indices], helper, logical(1))
return(out)
}
is.prime(c(17,5,10,22,109,55))
# [1] TRUE TRUE FALSE FALSE TRUE FALSE
全矢量化
如果性能受到威胁,您可以考虑使用 `Rcpp`:c++文件
#include <Rcpp.h>
#include <math.h>
using namespace Rcpp;
bool is_prime(int n) {
if ((n == 2) || (n == 3) || (n == 5)) {
return true;
}
if ((n % 2 == 0) || (n == 1)) {
return false;
}
int i = 3;
while (i < round(sqrt(n)) + 1) {
if (n % i == 0) {
return false;
}
i += 2;
}
return true;
}
// [[Rcpp::export]]
LogicalVector is_prime(IntegerVector v) {
int n = v.length();
LogicalVector out = LogicalVector(n);
for (int i = 0; i < n; i++) {
out[i] = is_prime(v[i]);
}
return out;
}
R 文件
library(Rcpp)
sourceCpp('prime_fun.cpp') # if cpp file in same dir
is_prime(c(17,5,10,22,109,55))
# [1] TRUE TRUE FALSE FALSE TRUE FALSE
R 本质上是一种矢量化语言,您只需在编写函数时不要破坏它...
is.prime <- function(num){
res<-rep(TRUE, length(num))
for(i in 2:(max(num)-1) ){
res[(i < num) & ((num %% i) == 0) ] <- FALSE
}
return(res)
}
x<-c(2, 5, 17, 109, 10, 22, 55, 93)
print("Primes:")
print(x[ is.prime(x) ] )
输出:
> source('~/.active-rstudio-document')
[1] "Primes:"
[1] 2 5 17 109