【问题标题】:R self referenceR 自参考
【发布时间】:2011-12-07 19:05:06
【问题描述】:

在 R 中,我发现自己经常做这样的事情:

adataframe[adataframe$col==something]<-adataframe[adataframe$col==something)]+1

这种方式有点冗长乏味。有什么办法适合我
引用我要更改的对象,例如

adataframe[adataframe$col==something]<-$self+1 

?

【问题讨论】:

标签: r dataframe self-reference


【解决方案1】:

您应该更多地关注 Gabor Grothendeick(而不仅仅是在这种情况下。)Matt Asher 博客上引用的 inc 函数可以满足您的所有要求:

(而且明显的扩展也有效。)

add <- function(x, inc=1) {
   eval.parent(substitute(x <- x + inc))
 }
# Testing the `inc` function behavior

编辑:在我对第一条评论中没有得到批准感到暂时烦恼之后,我接受了添加另一个函数参数的挑战。提供数据帧一部分的一个参数,它仍然会将值的范围增加一。到目前为止,仅在中缀二元运算符上进行了非常轻微的测试,但我认为它没有理由不适用于仅接受两个参数的任何函数:

transfn <- function(x, func="+", inc=1) {
   eval.parent(substitute(x <- do.call(func, list(x , inc)))) }

(认罪:从传统的 R 角度来看,这在某种程度上“感觉不对”,即返回赋值进行赋值。)inc 函数的早期测试如下:

df <- data.frame(a1 =1:10, a2=21:30, b=1:2)
 inc <- function(x) {
   eval.parent(substitute(x <- x + 1))
 }

#---- examples===============>

> 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

【讨论】:

  • 如果我要多次执行相同的操作,那就太棒了,但是如果我只需要在定义 inc 函数后执行该操作就不值得花时间
  • 有些人就是不能满足。
  • 大声笑,如果这是我能得到的最好的,我会接受的。我只是想看看是否有更简单的解决方案,因为我对所有现有的 R 函数都不太熟悉
  • 即使transfn 也有可能通过使用“...”参数列表来概括。根据您的用户名进行适当的调查。
【解决方案2】:

尝试包data.table 及其:= 运算符。它非常快而且非常短。

DT[col1==something, col2:=col3+1]

第一部分col1==something 是子集。您可以在此处放置任何内容并使用列名,就好像它们是变量一样;即,无需使用$。然后第二部分col2:=col3+1 将 RHS 分配给该子集中的 LHS,其中列名可以像变量一样分配。 := 是引用赋值。不复制任何对象,因此比 &lt;-=withintransform 更快。

另外,即将在 v1.8.1 中实现,j 语法的一个最终目标是允许 :=j 中,就像将它与 by 结合起来,请参阅问题:when should I use the := operator in data.table

UDPDATE :确实是在 2012 年 7 月发布的(:= by group)。

【讨论】:

  • 而且可能比我的产品经过严格的测试。
  • 包可以改变基本语言操作符???我认为包只是一堆函数/数据!
  • 问题:您可以只使用DT[col1...] 而不是DT[DT$col1...]
  • @TomasT.:你可以。请注意,如果 col1 被索引,DT[col1="a",] 执行矢量扫描,而DT["a",] 执行二进制搜索。
  • @tomas-t := 不是基本的语言运算符。它未被 R 未使用和未定义,但可以定义。
【解决方案3】:

我会偏爱(大概子集在行上)

ridx <- adataframe$col==something
adataframe[ridx,] <- adataframe[ridx,] + 1

它不依赖于任何花哨/脆弱的解析,可以合理地表达正在执行的操作,并且不太冗长。还倾向于将行分解成人类可以解析的单元,并且使用标准习语有一些吸引力——R 的词汇和特质已经足够我的口味了。

【讨论】:

  • 如果有的话,最后一句可以添加到 SO.fortunes 包中。
【解决方案4】:

这是你可以做的。假设您有一个数据框

df = data.frame(x = 1:10, y = rnorm(10))

并且您想将所有 y 递增 1。您可以使用 transform 轻松完成此操作

df = transform(df, y = y + 1)

【讨论】:

  • 还有df &lt;- within(df, y&lt;- y+1),比transform更通用。
  • 不过,这仍然有点烦人。也就是说,如果我只想增加 y 值小于 1,我仍然需要写 df=transfrom(df, y[y&lt;1]&lt;-y[y&lt;1]+1
猜你喜欢
  • 2011-11-11
  • 1970-01-01
  • 1970-01-01
  • 2017-02-13
  • 2012-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-12
相关资源
最近更新 更多