在R中的单行中,在LHS上分配多个新variables

我想在R中的一行中分配多个variables。是否可以做这样的事情?

values # initialize some vector of values (a, b) = values[c(2,4)] # assign a and b to values at 2 and 4 indices of 'values' 

通常我想在一行中分配5-6个variables,而不是多行。 有其他select吗?

在挣扎的问题博客上有一个很好的答案

这是从那里采取的,只是很小的修改。

使用以下三个function(加一个允许不同大小的列表)

 # Generic form '%=%' = function(l, r, ...) UseMethod('%=%') # Binary Operator '%=%.lbunch' = function(l, r, ...) { Envir = as.environment(-1) if (length(r) > length(l)) warning("RHS has more args than LHS. Only first", length(l), "used.") if (length(l) > length(r)) { warning("LHS has more args than RHS. RHS will be repeated.") r <- extendToMatch(r, l) } for (II in 1:length(l)) { do.call('<-', list(l[[II]], r[[II]]), envir=Envir) } } # Used if LHS is larger than RHS extendToMatch <- function(source, destin) { s <- length(source) d <- length(destin) # Assume that destin is a length when it is a single number and source is not if(d==1 && s>1 && !is.null(as.numeric(destin))) d <- destin dif <- d - s if (dif > 0) { source <- rep(source, ceiling(d/s))[1:d] } return (source) } # Grouping the left hand side g = function(...) { List = as.list(substitute(list(...)))[-1L] class(List) = 'lbunch' return(List) } 

然后执行:

使用新函数g()将左侧分组右侧应该是向量或列表使用新创build的二元运算符%=%

 # Example Call; Note the use of g() AND `%=%` # Right-hand side can be a list or vector g(a, b, c) %=% list("hello", 123, list("apples, oranges")) g(d, e, f) %=% 101:103 # Results: > a [1] "hello" > b [1] 123 > c [[1]] [1] "apples, oranges" > d [1] 101 > e [1] 102 > f [1] 103 

使用不同大小的列表的示例:

更长的左手边

 g(x, y, z) %=% list("first", "second") # Warning message: # In `%=%.lbunch`(g(x, y, z), list("first", "second")) : # LHS has more args than RHS. RHS will be repeated. > x [1] "first" > y [1] "second" > z [1] "first" 

更长的右手边

 g(j, k) %=% list("first", "second", "third") # Warning message: # In `%=%.lbunch`(g(j, k), list("first", "second", "third")) : # RHS has more args than LHS. Only first2used. > j [1] "first" > k [1] "second" 

考虑使用基本R中包含的function

例如,创build一个1行数据框(比如V )并初始化你的variables。 现在你可以一次赋值给多个variablesV[,c("a", "b")] <- values[c(2, 4)] ,通过名字( V$a )调用每个variables,它们同时( values[c(5, 6)] <- V[,c("a", "b")] )。

如果你懒惰,不想绕过从数据框调用variables,你可以attach(V) (尽pipe我个人从来没有这样做)。

 # Initialize values values <- 1:100 # V for variables V <- data.frame(a=NA, b=NA, c=NA, d=NA, e=NA) # Assign elements from a vector V[, c("a", "b", "e")] = values[c(2,4, 8)] # Also other class V[, "d"] <- "R" # Use your variables V$a V$b V$c # OOps, NA V$d V$e 

这是我的想法。 语法可能很简单:

 `%tin%` <- function(x, y) { mapply(assign, as.character(substitute(x)[-1]), y, MoreArgs = list(envir = parent.frame())) invisible() } c(a, b) %tin% c(1, 2) 

给出这样的:

 > a Error: object 'a' not found > b Error: object 'b' not found > c(a, b) %tin% c(1, 2) > a [1] 1 > b [1] 2 

这并没有得到很好的testing。

正如其他人所解释的那样,似乎没有内置任何东西……但是你可以devise一个vassign函数,如下所示:

 vassign <- function(..., values, envir=parent.frame()) { vars <- as.character(substitute(...())) values <- rep(values, length.out=length(vars)) for(i in seq_along(vars)) { assign(vars[[i]], values[[i]], envir) } } # Then test it vals <- 11:14 vassign(aa,bb,cc,dd, values=vals) cc # 13 

有一件事要考虑的是如何处理你的情况,例如,指定3个variables和5个值或其他方式。 这里我简单地重复(或截断)与variables长度相同的值。 也许警告是谨慎的。 但它允许以下内容:

 vassign(aa,bb,cc,dd, values=0) cc # 0 

一个潜在的危险(就像使用assign是有风险的)选项是向Vectorize assign

 assignVec <- Vectorize("assign",c("x","value")) #.GlobalEnv is probably not what one wants in general; see below. assignVec(c('a','b'),c(0,4),envir = .GlobalEnv) ab 0 4 > b [1] 4 > a [1] 0 

或者我想你可以使用自己的函数手动vector化它自己的函数,也许使用mapply参数的一个合理的默认值。 例如, Vectorize将返回一个具有相同的assign环境属性的函数,在这种情况下是namespace:base ,或者你可以设置envir = parent.env(environment(assignVec))

如果你唯一的要求是有一行代码,那么怎么样:

 > a<-values[2]; b<-values[4] 

https://stat.ethz.ch/R-manual/R-devel/library/base/html/list2env.html

 list2env( list( a=1, b=2:4, c=rpois(10,10), d=gl(3,4,LETTERS[9:11]) ), envir=.GlobalEnv ) 

恐怕你所寻找的elegent解决scheme(如c(a, b) = c(2, 4) )不幸不存在。 但是不要放弃,我不确定! 我能想到的最接近的解决scheme是:

 attach(data.frame(a = 2, b = 4)) 

或者如果您对警告感到困扰,请将其closures:

 attach(data.frame(a = 2, b = 4), warn = F) 

但是我想你对这个解决scheme不满意,我也不会

 R> values = c(1,2,3,4) R> a <- values[2]; b <- values[3]; c <- values[4] R> a [1] 2 R> b [1] 3 R> c [1] 4 

我放了一个R包zeallot来解决这个问题。 zeallot包含一个运算符( %<-% ),用于解包,多重和解构赋值。 赋值expression式的LHS使用对c()调用来构build。 赋值expression式的RHS可以是任何返回的expression式,也可以是向量,列表,嵌套列表,数据框,string,date对象或自定义对象(假设有一个解构架实现)。

这里是使用zeallot(最新版本,0.0.5)返工的最初的问题。

 library(zeallot) values <- c(1, 2, 3, 4) # initialize a vector of values c(a, b) %<-% values[c(2, 4)] # assign `a` and `b` a #[1] 2 b #[1] 4 

有关更多示例和信息,可以查看包装小插图 。

我已经尝试过Hadd E. Nuff的类似问题的解决scheme。 它会抛出一个错误“参数”nm“缺less,没有默认值”。 我尝试了“list2env(setNames(as.list(rep(2,5)),letters [1:5]),.GlobalEnv)”,它符合我的目的,即将5个2分配给前5个字母。

recursion的另一个版本:

 let <- function(..., env = parent.frame()) { f <- function(x, ..., i = 1) { if(is.null(substitute(...))){ if(length(x) == 1) x <- rep(x, i - 1); stopifnot(length(x) == i - 1) return(x); } val <- f(..., i = i + 1); assign(deparse(substitute(x)), val[[i]], env = env); return(val) } f(...) } 

例:

 > let(a, b, 4:10) [1] 4 5 6 7 8 9 10 > a [1] 4 > b [1] 5 > let(c, d, e, f, c(4, 3, 2, 1)) [1] 4 3 2 1 > c [1] 4 > f [1] 1 

我的版本:

 let <- function(x, value) { mapply( assign, as.character(substitute(x)[-1]), value, MoreArgs = list(envir = parent.frame())) invisible() } 

例:

 > let(c(x, y), 1:2 + 3) > x [1] 4 > y [1] 

你的意思是你想重新分配向量中的元素? 如果是这样,那么只是:

 values[c(2,4)] <- c(a, b)