한 줄로 LHS에 여러 새 변수 할당
R에서 한 줄에 여러 변수를 할당하고 싶습니다. 이와 같은 작업을 수행 할 수 있습니까?
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 개의 변수를 할당하고 싶습니다. 대안이 있습니까?
문제 해결 블로그 에 훌륭한 답변이 있습니다.
이것은 아주 사소한 수정으로 거기에서 가져옵니다.
다음 세 가지 기능 사용 (다른 크기의 목록을 허용하는 기능 추가)
# 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()
. 오른쪽은 벡터 또는 목록이어야합니다. 새로 생성 된 이항 연산자를 사용합니다.%=%
# 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에 포함 된 기능을 사용.
예를 들어 1 행 데이터 프레임 (예 :)을 생성하고 그 V
안에 변수를 초기화합니다. 이제 한 번에 여러 변수에 할당 전역, V[,c("a", "b")] <- values[c(2, 4)]
이름으로 각각의 호출 V$a
하거나 ( ), 여러 변수를 동시에 사용할 수 있습니다 ( values[c(5, 6)] <- V[,c("a", "b")]
).
게으르고 데이터 프레임에서 변수를 호출하고 싶지 않다면 할 수 있습니다 attach(V)
(개인적으로는 그렇게하지 않습니다).
# 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
저는 이 문제를 해결하기 위해 R 패키지 열광 튼 모았 습니다. zeallot에는 %<-%
압축 해제, 및 multi- 구조 분해 할당을위한 연산자 ( )가 포함 됩니다. 할당 할당의 LHS는 c()
. 식의 RHS는 벡터, 목록, 중첩 목록, 데이터 프레임, 최소, 날짜 개체 또는 사용자 지정 개체 ( 구현하는 식의 할당 개체 )를 반환하거나 반환하는 식일 수 있습니다 .destructure
다음은 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
더 많은 예와 정보를 보려면 패키지 비 네트를 확인하십시오 .
여기 내 생각이 있습니다. 아마도 구문은 매우 간단합니다.
`%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
이것은 잘 테스트되지 않습니다.
잠재적으로 위험한 (하는 사용 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)
a b
0 4
> b
[1] 4
> a
[1] 0
또는 인수에 mapply
합당한 합법을 사용 하여하여 자신의 함수를 사용하여 수동으로 벡터화 할 수 envir
있습니다. 를 들어은 예 Vectorize
과 동일한 Environmental & 속성을 가진 함수를 반환합니다 assign
.이 경우는입니다 namespace:base
. 또는 그냥 접근 할 수 있습니다 envir = parent.env(environment(assignVec))
.
다른 사람들이 설명했듯이 내장 된 것이없는 것입니다. ...하지만 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 개의 변수와 5 개의 값을 지정하거나 그 반대의 경우를 처리하는 방법입니다. 여기서는 변수와 같은 길이가되도록 값을 반복 (또는 잘라 내기)합니다. 아마도 경고는 신중할 것입니다. 그러나 다음을 허용합니다.
vassign(aa,bb,cc,dd, values=0)
cc # 0
단 한 줄의 코드 만 사용하는 것이 유일한 요구 사항이라면 다음을 수행하십시오.
> 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
)
최근 비슷한 문제가 있었고 여기에 사용하려고 시도했습니다. purrr::walk2
purrr::walk2(letters,1:26,assign,envir =parent.frame())
list2env(setNames(as.list(rep(2,5)), letters[1:5]), .GlobalEnv)
내 목적을 달성했습니다. 즉, 처음 5 개의 글자에 5 개의 2를 할당하는 것입니다.
찾고있는 elegent 솔루션 (예 c(a, b) = c(2, 4)
: 불편하게)이 존재하지 않는 것이 두렵습니다 . 하지만 포기하지 마세요. 잘 모르겠습니다! 내가 생각할 수있는 가장 가까운 해결책은 다음과 같습니다.
attach(data.frame(a = 2, b = 4))
또는 경고가 신경 쓰이는 경우 끄십시오.
attach(data.frame(a = 2, b = 4), warn = F)
하지만이 솔루션에 만족하지 않는다고 생각합니다. 나도 마찬가지입니다.
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
재귀가있는 다른 버전 :
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]
여기에 제공된 답변 중 일부 + 약간의 소금을 결합하면이 솔루션은 어떻습니까?
assignVec <- Vectorize("assign", c("x", "value"))
`%<<-%` <- function(x, value) invisible(assignVec(x, value, envir = .GlobalEnv))
c("a", "b") %<<-% c(2, 4)
a
## [1] 2
b
## [1] 4
여기에 R 섹션을 추가하는 데 사용했습니다. http://rosettacode.org/wiki/Sort_three_variables#R
주의 사항 : 전역 변수 (예 :)를 할당하는 경우에만 작동합니다 <<-
. 더 나은, 더 일반적인 해결책이 있다면 pls. 댓글로 알려주세요.
참고 URL : https://stackoverflow.com/questions/7519790/assign-multiple-new-variables-on-lhs-in-a-single-line
'ProgramingTip' 카테고리의 다른 글
Razor보기에서 인코딩되지 않은 암호화 된 내보내기 (0) | 2020.10.12 |
---|---|
PHP로 SFTP하는 방법? (0) | 2020.10.12 |
iOS5 Storyboard UIViewController 어떤 init 메소드가 스토리 보드에서 호출? (0) | 2020.10.12 |
Perl에서 "eq"대 "=="문자열 비교 (0) | 2020.10.12 |
왜 'git log'를 퇴직해야합니까? (0) | 2020.10.12 |