是否有某种方法可以使R对矢量和其他序列数据结构使用基于零的索引,如下所示,例如在C和python中。
我们有一些代码在C中进行一些数值处理,我们正在考虑将其移植到R中以利用其高级统计函数,但是基于零的索引缺乏(根据我的谷歌搜索后的理解)使得任务有点困难。
答案 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 - 并且只要您编写方括号,就可以训练自己使用它。在我看来,我决定使用这个点,因为它足够大,可以被感知,但不会太大,不能使代码变得混乱。
上面的例子很简单,但如果我们需要进行更复杂的变量转换,例如(对于[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;)。