R自我参考
在RI发现自己做了很多这样的事情:
adataframe[adataframe$col==something]<-adataframe[adataframe$col==something)]+1
这种方式是漫长而乏味的。 有没有办法给我
引用我正在尝试改变的对象
adataframe[adataframe$col==something]<-$self+1
?
试试package data.table和它:=
运算符。 这是非常快,非常短。
DT[col1==something, col2:=col3+1]
第一部分col1==something
是子集。 你可以在这里放置任何东西,并使用列名,就好像它们是variables一样; 即不需要使用$
。 然后第二部分col2:=col3+1
将该RHS分配给该子集中的LHS,其中列名可以被分配到,就好像它们是variables一样。 :=
是按引用分配的。 没有任何对象的副本被采用,所以比<-
, =
, within
和transform
更快。
另外,即将在v1.8.1中实现, j
的语法的一个最终目标是允许:=
在j
就像它将它和by
组合起来一样,看问题: 我应该何时在data.table中使用:=
运算符 。
UDPDATE:2012年7月确实发布了( :=
按组)。
你应该更加关注Gabor Grothendeick(而不仅仅是在这个例子中)。Matt Asher的博客中引用的inc
函数完成了你所问的所有内容:
(而且明显的扩展也是如此。)
add <- function(x, inc=1) { eval.parent(substitute(x <- x + inc)) } # Testing the `inc` function behavior
编辑:在第一个评论缺乏批准之后,我暂时感到烦恼之后,我接受了添加更多function参数的挑战。 提供一个dataframe的一部分参数,它仍然会增加值的范围一。 到目前为止,只在中缀运算符上进行了非常简单的testing,但是我没有理由认为它不适用于只接受两个参数的函数:
transfn <- function(x, func="+", inc=1) { eval.parent(substitute(x <- do.call(func, list(x , inc)))) }
(有罪承认:这从某种意义上来说,从传统的R值的angular度来看是“错误的”)。早期对inc
函数的testing如下:
> df <- data.frame(a1 =1:10, a2=21:30, b=1:2) > inc <- function(x) { + eval.parent(substitute(x <- x + 1)) + } > inc(df$a1) # works on whole columns > df a1 a2 b 1 2 21 1 2 3 22 2 3 4 23 1 4 5 24 2 5 6 25 1 6 7 26 2 7 8 27 1 8 9 28 2 9 10 29 1 10 11 30 2 > inc(df$a1[df$a1>5]) # testing on a restricted range of one column > df a1 a2 b 1 2 21 1 2 3 22 2 3 4 23 1 4 5 24 2 5 7 25 1 6 8 26 2 7 9 27 1 8 10 28 2 9 11 29 1 10 12 30 2 > inc(df[ df$a1>5, ]) #testing on a range of rows for all columns being transformed > df a1 a2 b 1 2 21 1 2 3 22 2 3 4 23 1 4 5 24 2 5 8 26 2 6 9 27 3 7 10 28 2 8 11 29 3 9 12 30 2 10 13 31 3 # and even in selected rows and grepped names of columns meeting a criterion > inc(df[ df$a1 <= 3, grep("a", names(df)) ]) > df a1 a2 b 1 3 22 1 2 4 23 2 3 4 23 1 4 5 24 2 5 8 26 2 6 9 27 3 7 10 28 2 8 11 29 3 9 12 30 2 10 13 31 3
这是你可以做的。 让我们说你有一个数据框
df = data.frame(x = 1:10, y = rnorm(10))
而且你想把所有的y
加1。你可以通过使用transform
轻松完成
df = transform(df, y = y + 1)
我会偏向(可能是子集在行上)
ridx <- adataframe$col==something adataframe[ridx,] <- adataframe[ridx,] + 1
不依赖任何花哨的/脆弱的parsing,对于正在执行的操作是合理的expression,而不是太冗长。 也倾向于将线条划分成很好的人类可分解单位,并且使用标准习语有一些吸引力–R的词汇和特质已经足够我的口味。