R中基于零的数组/向量

时间:2014-08-14 11:59:59

标签: r indexing

是否有某种方法可以使R对矢量和其他序列数据结构使用基于零的索引,如下所示,例如在C和python中。

我们有一些代码在C中进行一些数值处理,我们正在考虑将其移植到R中以利用其高级统计函数,但是基于零的索引缺乏(根据我的谷歌搜索后的理解)使得任务有点困难。

5 个答案:

答案 0 :(得分:4)

TL; DR:不要这样做!

我不认为基于零/一的索引是将C代码移植到R的主要障碍。 但是,如果您确实认为有必要这样做,您当然可以覆盖.Primitive('[')函数,更改R中索引/子集的行为。

# rename the original `[`
> index1 <- .Primitive('[')

# WICKED!: override `[`. 
> `[` <- function(v, i) index1(v, i+1)
> x <- 1:5
> x[0]
[1] 1
> x[1]
[1] 2
> x[0:2]
[1] 1 2 3

但是,这可能会非常危险,因为您更改了基本的索引行为,并且可能会对使用子集和索引的所有库和函数造成意外的级联效应。

例如,因为子集化和索引可以接受其他类型的数据作为选择器(比如说布尔向量),并且简单的重写函数没有考虑到这一点,你可能会有非常奇怪的行为:

> x[x > 2] # x > 2 returns a boolean vector, and by + 1, you convert 
           # boolean FALSE/TRUE to numeric 0/1
[1] 1 1 2 2 2

虽然可以通过修改覆盖功能来解决此问题,但您仍可能遇到其他问题。

另一个例子:

> (idx <- which(x > 2)) # which() still gives you 1-based index
> x[idx]
[1]  4  5 NA

你永远不知道事情可能会出错的地方。所以,只是不要。

答案 1 :(得分:1)

您可以制作“辅助”索引,以便在R。

中使用基于0的构造更方便地工作

这是个主意。假设我们需要计算[0]中整数x上的y(x)= x ^ 2; 10]:

x <- 0:10 # 0 based index for calculations
y <- c()
y[x+1] <- x^2 # have to add 1 when indexing y

x. <- x+1 # auxiliary 1 based index for R vectors indexing    
y <- c()
y[x.] <- x^2 # no need to remember to add 1

只需选择适合您的辅助索引的命名模式:它可以是x1或x_1 - 并且只要您编写方括号,就可以训练自己使用它。在我看来,我决定使用这个点,因为它足够大,可以被感知,但不会太大,不能使代码变得混乱。

上面的例子很简单,但如果我们需要进行更复杂的变量转换,例如y_i = x_{i+1}*a^{i+1} + x_i*a^i(对于[0; 10]中的i),那么关注其他索引会收费:

i <- 0:10
y[i+1] <- x[i+2]*a^(i+1) + x[i+1]*a^i # does not resemble 
                                      # the original formula

i. <- i+1
y[i.] <- x[i.+1]*a^(i+1) + x[i.]*a^i # Now it is easier to see the
                                     # original formula behind this

正如您所看到的,代码变得更加清晰,在检查错误代码时更容易将其与原始公式进行比较。

答案 2 :(得分:1)

我想发展辛寅的答案。 可以为此类定义新类(如 c = cars %>% mutate(var1 = dist*speed)%>% {. ->> b } %>% #here is save summary() c head(b) ),方法zero-based_vector,然后将此类分配给目标向量的属性。

[

顺便说一句,没有什么会被打破,因为我们不会覆盖# define new method for our custom class index1 <- .Primitive('[') `[.zero-based_vector` <- function(v, i) index1(as.vector(v), i+1) x <- letters # make `x` a zero-bazed_vector class(x) <- c("zero-based_vector", class(x)) # it works! x[0:3] # [1] "a" "b" "c" "d"

答案 3 :(得分:0)

例如,如果你想要矩阵索引(1..3,1..3)为你的矩阵G有索引(0..2,0..2),你想要读取像G这样的条目(0, 2)并输入类似G(0,2)= 5的条目,然后可以使用以下解决方法:

{{1}}

这里G(0,2,5)就像G(0,2)= 5,如果你输入G(0,2),你得到条目5,这意味着你可以进行像erg = G(0, 2)+ 3。 为了使用以0开头的索引而不是1,你只需将索引移动1并使用辅助矩阵GG。

答案 4 :(得分:0)

另一种方式是以下(这里是3x3矩阵的例子):

n         = 3;
GG        = matrix( (1:(n+1)^2)*0, n+1, n+1);

cl        = 0;

G         = function(i,j){ return(GG[i+1, j+1]) } 

':='      = function(GAuf,x){

       cl <<- match.call();
       aa = deparse(cl$GAuf);
       d1 = gregexpr(pattern="\\(", aa)
       d2 = gregexpr(pattern=",", aa)
       s1 = d1[[1]][1] + 1;
       s2 = d2[[1]][1] - 1;
       i  = substr(aa, s1, s2);
       d1 = gregexpr(pattern=" ", aa)
       d2 = gregexpr(pattern=")", aa)
       s1 = d1[[1]][1]+1;
       s2 = d2[[1]][1]-1;
       j  = substr(aa, s1, s2);
       d  = gregexpr(pattern="\\(", aa);
       s  = d[[1]][1]-1;
       fn = substr(aa, 1, s);

       com= paste(fn,fn, "[", i,"+1,", j,"+1]","<<-x", sep="");

       eval(parse(text=com));

}

现在您可以按

设置值
G(0,1) := 2

并通过

获取值
> G(0,1)

[1] 2

请注意,我使用的惯例是,如果您使用名为&#39; N&#39;然后功能&#39;:=&#39;期望一个名为&#39; NN&#39; (这里是矩阵&#39; G&#39; GG&#39;),你可以在函数的末尾看到&#39;:=&#39;因为字符串&#39; com&#39;由粘贴(fn,fn,...)&#39;设置。如果你想命名你的矩阵&#34;你好&#34;然后你必须定义一个矩阵&#34; hellohello&#34; (比如矩阵&#39; GG&#39;)和矩阵&#34;你好&#34; (比如矩阵&#39; G&#39;)。