একক লাইনে একাধিক নতুন ভেরিয়েবল এলএইচএসে বরাদ্দ করুন


90

আমি আর একটি একক লাইনে একাধিক ভেরিয়েবল বরাদ্দ করতে চাই Is এটির মতো কিছু করা কি সম্ভব?

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 ভেরিয়েবলগুলি বরাদ্দ করতে চাই। বিকল্প আছে?


আপনি পিএইচপি মধ্যে কিছু মানে list($a, $b) = array(1, 2)? সেটা ভালো হবে! +1
টিএমএস

@ টমাস টি - আমি মনে করি vassignনীচে আমার পরামর্শটি কাছে এসেছে ... :)
টমি

দ্রষ্টব্য: এই বি আর এর জন্য সেমিকোলনের প্রয়োজন নেই
Iterator

4
যদি আপনি এটি একটি উপযুক্ত পরিবেশের মধ্যে চেষ্টা করে দেখেন তবে এটি তত সহজ X <- list();X[c('a','b')] <- values[c(2,4)]। ঠিক আছে, আপনি তাদের কর্মক্ষেত্রে বরাদ্দ করবেন না, তবে তাদের তালিকাতে খুব সুন্দরভাবে রাখবেন keep আমি এইভাবে এটি করতে পছন্দ করব
জোরিস

7
আমি পাইথন পছন্দ করি, মাত্র a, b = 1,2। নীচের সমস্ত উত্তর 100x আরও শক্ত
AppleLover

উত্তর:


40

স্ট্রাগলিং থ্রু সমস্যা ব্লগের একটি দুর্দান্ত উত্তর রয়েছে

এটি সেখান থেকে নেওয়া হয়েছে, খুব সামান্য পরিবর্তন সহ।

তিনটি ফাংশন অনুসরণ করে (বিভিন্ন আকারের তালিকার অনুমতি দেওয়ার জন্য প্লাস ওয়ান) ব্যবহার করা হচ্ছে

# 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"

34

বেস আর এর সাথে অন্তর্ভুক্ত কার্যকারিতা ব্যবহার বিবেচনা করুন

উদাহরণস্বরূপ, একটি 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

4
আমি পারলে +10। আমি অবাক হয়েছি কেন লোকেরা এ জাতীয় সুস্পষ্ট মামলায় তালিকাগুলি ব্যবহার করতে অস্বীকার করে, বরং টন অর্থহীন ভেরিয়েবলগুলির সাথে ওয়ার্কস্পেসে লিটার দেয়। (আপনি তালিকাগুলি ডেটা হিসাবে ব্যবহার করেন
ra ফ্রেম

তবে একই কলামে আপনার বিভিন্ন ধরণের উপাদান থাকতে পারে না, বা আপনার ডেটাফ্রেমের ভিতরে ডেটাফ্রেম বা তালিকা সংরক্ষণ করতে পারবেন না
স্ক্যান

4
আসলে, আপনি একটি ডেটা ফ্রেমে তালিকাগুলি সঞ্চয় করতে পারেন - গুগল "তালিকা কলাম"।

এটি কোনও খারাপ পন্থা নয়, এর কিছু সুবিধা রয়েছে তবে অনেক ব্যবহারকারী কেন এই পদ্ধতিতে নির্ধারিত ভেরিয়েবলগুলি ব্যবহার করতে বা অ্যাক্সেস করার চেষ্টা করছেন তাই প্রতিবার কেন ডেটা.ফ্রেম সিনট্যাক্স নিয়ে কাজ করতে চান না তা কল্পনাও করা খুব কঠিন নয়।
ব্র্যান্ডন

34

এই সমস্যাটি মোকাবেলায় আমি একটি আর প্যাকেজ জিলোট একসাথে রেখেছি । জেললট %<-%আনপ্যাকিং, একাধিক এবং ডেস্ট্রাকচারিং অ্যাসাইনমেন্টের জন্য একটি অপারেটর ( ) অন্তর্ভুক্ত করে । অ্যাসাইনমেন্ট এক্সপ্রেশনটির এলএইচএস কল ব্যবহার করে নির্মিত হয় c()। অ্যাসাইনমেন্ট এক্সপ্রেশনটির আরএইচএস এমন কোনও এক্সপ্রেশন হতে পারে যা ভেক্টর, তালিকা, নেস্টেড তালিকা, ডেটা ফ্রেম, চরিত্রের স্ট্রিং, তারিখের অবজেক্ট বা কাস্টম অবজেক্টস (ধরে নিচ্ছে destructureবাস্তবায়ন রয়েছে)।

এখানে জেলোট (সর্বশেষ সংস্করণ, ০.০.৫) ব্যবহার করে প্রাথমিক প্রশ্নটি করা হয়েছে question

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

আরও উদাহরণ এবং তথ্যের জন্য প্যাকেজ ভিগনেট পরীক্ষা করতে পারেন ।


ঠিক এটিই আমি খুঁজে প্রত্যাশা করছিলাম, একটি অজগর জাতীয় সিনট্যাক্স সক্ষম করে যা ওপি চেয়েছিল, একটি আর প্যাকেজে প্রয়োগ করা হয়েছিল
জাফেল্ডস

4
প্রতিটি চলক নামের একটি ম্যাট্রিক্স নির্ধারণ সম্পর্কে কি?
স্ট্যাটাসস্রেস্রেস

14

এখানে আমার ধারণা। সম্ভবত বাক্য গঠনটি বেশ সহজ:

`%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

এটি যদিও ভাল পরীক্ষা করা হয় না।


4
কোশকে, আমার কাছে খুব সুন্দর লাগছে :-) তবে অপারেটর অগ্রাধিকার সম্পর্কে আমি কিছুটা উদ্বিগ্ন:%%% অপারেটরগুলি বেশ উঁচুতে রয়েছে, সুতরাং উদাহরণস্বরূপ c(c, d) %tin% c(1, 2) + 3(=> সি = 1, ডি = 1) এর আচরণগত সংখ্যা ফিরে আসে ( 0)) অবাক করা হিসাবে বিবেচনা করা যেতে পারে।
এসবিএল

10

একটি সম্ভাব্য বিপজ্জনক (যতটা ব্যবহার 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একই পরিবেশের বৈশিষ্ট্যগুলির সাথে একটি ফাংশন ফিরিয়ে দেবে assign, যা এই ক্ষেত্রে হয় namespace:baseবা আপনি ঠিক সেট করতে পারেন envir = parent.env(environment(assignVec))


9

অন্যরা যেমন ব্যাখ্যা করেছে, তেমন কিছু অন্তর্নির্মিত বলে মনে হচ্ছে না ... ... তবে আপনি নীচে 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

আমি এটি পছন্দ করি তবে আমি উদ্বেগ প্রকাশ করব যে এটি কোনও ক্ষেত্রেই ভেঙে যেতে পারে যেখানে এটি কোনও ফাংশন থেকেই ডেকে আনা হয়েছিল (যদিও এটির একটি সাধারণ পরীক্ষা আমার হালকা অবাক হওয়ার জন্য)। আপনি কি ব্যাখ্যা করতে পারেন ...(), যা আমার কাছে কালো যাদু বলে মনে হচ্ছে ...?
বেন বলকার

4
@ বেন বলকার - হ্যাঁ, ...()চরম কালো যাদু ;-)। এটি এমনভাবে ঘটে যখন "ফাংশন কল" ...()প্রতিস্থাপন করা হয়, তখন এটি একটি প্যারালিস্ট হয়ে যায় যা ভয়েলাতে পৌঁছে যেতে পারে as.character, আপনি স্ট্রিং হিসাবে যুক্তি পেয়েছিলেন ...
টমি

4
@ বেন বলকার - এবং এটি কোনও ফাংশন থেকে কল করার পরেও এটি সঠিকভাবে কাজ করা উচিত - যেহেতু এটি ব্যবহার envir=parent.frame()করতে পারে - এবং আপনি চাইলে উদাহরণস্বরূপ উল্লেখ envir=globalenv()করতে পারেন।
টমি

এমনকি কুলারেরও এটি প্রতিস্থাপনের কাজ হিসাবে থাকবে: `vassign<-` <- function (..., envir = parent.frame (), value)ইত্যাদি। যাইহোক, মনে হচ্ছে নির্ধারিত প্রথম অবজেক্টটির ইতিমধ্যে বিদ্যমান থাকা প্রয়োজন। কোন ধারনা?
এসবিএল

@ কেবেলাইটস - হ্যাঁ, এটি শীতল হবে তবে আমি মনে করি না যে আপনি প্রথম যুক্তির যে সীমাবদ্ধতা রয়েছে তার সীমাবদ্ধতার চারপাশে কাজ করতে পারেন - এজন্য এটিকে প্রতিস্থাপনের কাজ বলা হয় :) ... তবে অন্যথায় যদি এটি খুঁজে পান তবে আমাকে জানান !
টমি

6
list2env(setNames(as.list(rep(2,5)), letters[1:5]), .GlobalEnv)

আমার উদ্দেশ্যটি পরিবেশন করেছে, অর্থাত্ প্রথম পাঁচটি বর্ণের জন্য পাঁচ 2 টি সরবরাহ করে।



5

সম্প্রতি একটি অনুরূপ সমস্যা ছিল এবং এখানে আমার ব্যবহার চেষ্টা ছিল purrr::walk2

purrr::walk2(letters,1:26,assign,envir =parent.frame()) 

3

যদি আপনার একমাত্র প্রয়োজনে কোডের একক লাইন থাকে তবে কীভাবে:

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

4
একটি সংক্ষিপ্ত বিবৃতি খুঁজছিল কিন্তু আমার অনুমান যে সেখানে কিছুই নেই
ব্যবহারকারী 236215

আমি @ ব্যবহারকারী 236215 এর মতো একই নৌকায় আছি। ডানদিকে যখন কোনও ভেক্টর ফেরানো একটি জটিল ভাব হয়, তখন কোড পুনরাবৃত্তি করা খুব ভুল বলে মনে হয় ...
আকাশচুম্বী

1

আমি আশঙ্কা করছি যে আপনি যে ইলিজেন্ট সমাধানটি খুঁজছেন (যেমন c(a, b) = c(2, 4)) দুর্ভাগ্যজনকভাবে তার অস্তিত্ব নেই। তবে হাল ছাড়বেন না, আমি নিশ্চিত নই! আমি সবচেয়ে নিকটতম সমাধানটি ভাবতে পারি এটি হ'ল:

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

বা যদি আপনি সতর্কতা দিয়ে বিরক্ত হন তবে সেগুলি বন্ধ করুন:

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

তবে আমি মনে করি আপনি এই সমাধানটি নিয়ে সন্তুষ্ট নন, আমিও থাকব না ...


1
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

0

পুনরাবৃত্তি সহ অন্য সংস্করণ:

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] 

0

এখানে প্রদত্ত কয়েকটি উত্তর মিলিয়ে + সামান্য পরিমাণে নুন, কীভাবে এই সমাধান সম্পর্কে:

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

আমি এখানে আর বিভাগে যুক্ত করতে এটি ব্যবহার করেছি: http://rosettacode.org/wiki/Sort_three_variables#R

কেভেট: এটি কেবল গ্লোবাল ভেরিয়েবলগুলি (যেমন <<-) নির্ধারণের জন্য কাজ করে । যদি আরও ভাল, আরও সাধারণ সমাধান হয় তবে প্লিজ। মন্তব্য আমাকে বলুন.

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.