以点开头的 data.frame 的变量在 within() 中消失
Variables of a data.frame beginning by a dot disappear in within()
通过以点开头的名称调用变量是合法的(如 .identifier
)。但是,within()
函数不会保留它们。我错过了什么?或者这是一个错误?
A <- data.frame(.has.a.dot=1:10,has.no.dot=letters[1:10])
within(A, new.variable<-rnorm(10,.has.a.dot))
给出:
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
这似乎是因为 class environment
的 as.list
方法中的标准。标准参数是 all.names = FALSE
。来自 ?as.list
:
all.names a logical indicating whether to copy all values or
(default) only those whose names do not begin with a dot.
您可以将 within.data.frame
方法更改为以下内容:
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
}
然后你得到你预期的行为:
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
通过以点开头的名称调用变量是合法的(如 .identifier
)。但是,within()
函数不会保留它们。我错过了什么?或者这是一个错误?
A <- data.frame(.has.a.dot=1:10,has.no.dot=letters[1:10])
within(A, new.variable<-rnorm(10,.has.a.dot))
给出:
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
这似乎是因为 class environment
的 as.list
方法中的标准。标准参数是 all.names = FALSE
。来自 ?as.list
:
all.names a logical indicating whether to copy all values or (default) only those whose names do not begin with a dot.
您可以将 within.data.frame
方法更改为以下内容:
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
}
然后你得到你预期的行为:
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