Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variables of a data.frame beginning by a dot disappear in within()

It is legal to call a variable by a name that begins with a dot (like .identifier). However, within() function does not preserve them. Did I miss something? Or is it a bug?

A <- data.frame(.has.a.dot=1:10,has.no.dot=letters[1:10])
within(A, new.variable<-rnorm(10,.has.a.dot))

gives :

   has.no.dot new.variable
1           a     1.300361
2           b     3.014026
3           c     2.354260
4           d     4.261637
5           e     5.159326
6           f     7.178712
7           g     6.438039
8           h     8.253819
9           i     9.463351
10          j     8.828403
like image 538
Arthur Avatar asked Jan 09 '15 16:01

Arthur


People also ask

How do I remove a variable from data in R?

Using rm() command: When you want to clear a single variable from the R environment you can use the “rm()” command followed by the variable you want to remove. variable: that variable name you want to remove.

How do I select all variables in R?

You can shift-click to select a range of variables, you can hold shift and press the down key to select one or more variables, and so on. And then you can press Paste and the command with extracted variable names is pasted into your script editor.


1 Answers

This seems to be because of standard in the as.list method for class environment. The standard argument is all.names = FALSE. From ?as.list:

all.names a logical indicating whether to copy all values or (default) only those whose names do not begin with a dot.

You can change the within.data.frame method to the following:

within.data.frame <- function (data, expr, ...) 
{
  parent <- parent.frame()
  e <- evalq(environment(), data, parent)
  eval(substitute(expr), e)
  # l <- as.list(e) # removed this line
  l <- as.list(e, all.names=TRUE) # added this line
  l <- l[!sapply(l, is.null)]
  nD <- length(del <- setdiff(names(data), (nl <- names(l))))
  data[nl] <- l
  if (nD) 
    data[del] <- if (nD == 1) 
      NULL
  else vector("list", nD)
  data
}

Then you get your expected behavior:

within(A, new <- .has.a.dot)
##    .has.a.dot has.no.dot new
## 1           1          a   1
## 2           2          b   2
## 3           3          c   3
## 4           4          d   4
## 5           5          e   5
## 6           6          f   6
## 7           7          g   7
## 8           8          h   8
## 9           9          i   9
## 10         10          j  10
like image 60
shadow Avatar answered Sep 27 '22 20:09

shadow