আপনার নিজের ফাংশনটি লেখার সময় আর এর উপবৃত্ত বৈশিষ্ট্যটি কীভাবে ব্যবহার করবেন?


186

আর ভাষার একটি পরিবর্তনশীল সংখ্যক আর্গুমেন্ট নিতে পারে এমন ফাংশনগুলি সংজ্ঞায়িত করার জন্য নিফটি বৈশিষ্ট্য রয়েছে। উদাহরণস্বরূপ, ফাংশনটি data.frameঅনেকগুলি আর্গুমেন্ট গ্রহণ করে এবং প্রতিটি যুক্তি ফলাফল ডেটা সারণীর একটি কলামের ডেটা হয়ে যায়। ব্যবহারের উদাহরণ:

> data.frame(letters=c("a", "b", "c"), numbers=c(1,2,3), notes=c("do", "re", "mi"))
  letters numbers notes
1       a       1    do
2       b       2    re
3       c       3    mi

ফাংশনের স্বাক্ষরটিতে একটি উপবৃত্ত অন্তর্ভুক্ত রয়েছে:

function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE, 
    stringsAsFactors = default.stringsAsFactors()) 
{
    [FUNCTION DEFINITION HERE]
}

আমি এমন একটি ফাংশন লিখতে চাই যা অনুরূপ কিছু করে, একাধিক মান গ্রহণ করে এবং তাদেরকে একক রিটার্ন ভ্যালুতে সংহত করে তোলে (পাশাপাশি কিছু অন্যান্য প্রক্রিয়াজাতকরণ)। এটি করার জন্য, আমাকে কীভাবে ...ফাংশনের মধ্যে ফাংশনটির যুক্তিগুলি থেকে "আনপ্যাক" করতে হবে তা বুঝতে হবে । আমি জানি না এটি কীভাবে করা যায়। এর ফাংশন সংজ্ঞা প্রাসঙ্গিক লাইন data.frameহয় object <- as.list(substitute(list(...)))[-1L], যা আমি কোন অর্থে দেখা যায় না পারবেন না।

সুতরাং আমি কীভাবে উপবৃত্তিকে ফাংশনের স্বাক্ষর থেকে রূপান্তর করতে পারি, উদাহরণস্বরূপ, একটি তালিকায়?

আরও নির্দিষ্ট করে বলার জন্য, আমি কীভাবে get_list_from_ellipsisনীচের কোডটিতে লিখতে পারি ?

my_ellipsis_function(...) {
    input_list <- get_list_from_ellipsis(...)
    output_list <- lapply(X=input_list, FUN=do_something_interesting)
    return(output_list)
}

my_ellipsis_function(a=1:10,b=11:20,c=21:30)

সম্পাদন করা

এটি করার দুটি সম্ভাব্য উপায় আছে বলে মনে হয়। তারা as.list(substitute(list(...)))[-1L]এবং list(...)। যাইহোক, এই দুটি ঠিক একই জিনিস না। (পার্থক্যের জন্য, উত্তরের উদাহরণগুলি দেখুন)) কেউ আমাকে বলতে পারেন যে তাদের মধ্যে ব্যবহারিক পার্থক্য কী এবং আমার কোনটি ব্যবহার করা উচিত?

উত্তর:


113

আমি উত্তর এবং মন্তব্য পড়েছি এবং আমি দেখতে পাচ্ছি যে কয়েকটি বিষয় উল্লেখ করা হয়নি:

  1. data.framelist(...)সংস্করণ ব্যবহার করে । কোডের খণ্ডন:

    object <- as.list(substitute(list(...)))[-1L]
    mrn <- is.null(row.names)
    x <- list(...)

    objectকলামের নাম সহ কিছু যাদু করতে ব্যবহৃত হয়, তবে xচূড়ান্ত তৈরি করতে ব্যবহৃত হয় data.frame
    মূল্যহীন ...আর্গুমেন্ট ব্যবহারের জন্য write.csvকোডটি কোথায় match.callব্যবহার করা হয়েছে তা দেখুন।

  2. আপনি যেমন মন্তব্য মন্তব্যে লিখছেন উত্তর উত্তর তালিকার তালিকা নয়। দৈর্ঘ্য 4 এর একটি তালিকা, কোন উপাদানগুলি languageটাইপ হয়। প্রথম অবজেক্টটি হ'ল symbol- listদ্বিতীয়, এক্সপ্রেশন 1:10ইত্যাদি and এটি কেন [-1L]প্রয়োজন তা ব্যাখ্যা করে : এটি symbolসরবরাহিত আর্গুমেন্টগুলি থেকে প্রত্যাশিত অপসারণ করে ...(কারণ এটি সর্বদা একটি তালিকা থাকে)।
    যেহেতু ডার্ক substitute"পার্স গাছটিকে অবমূল্যায়নযোগ্য ভাব প্রকাশ করে" ফেরত দেয়।
    আপনি যখন কল করবেন my_ellipsis_function(a=1:10,b=11:20,c=21:30)তখন ...আর্গুমেন্টের একটি তালিকা "তৈরি" করে: list(a=1:10,b=11:20,c=21:30)এবং substituteএটিকে চারটি উপাদানের একটি তালিকা তৈরি করুন:

    List of 4
    $  : symbol list
    $ a: language 1:10
    $ b: language 11:20
    $ c: language 21:30

    প্রথম উপাদানটির কোনও নাম নেই এবং এটি [[1]]ডার্ক উত্তরে। আমি এই ফলাফলগুলি ব্যবহার করে অর্জন করেছি:

    my_ellipsis_function <- function(...) {
      input_list <- as.list(substitute(list(...)))
      str(input_list)
      NULL
    }
    my_ellipsis_function(a=1:10,b=11:20,c=21:30)
  3. উপরের মতো আমরা strকোনও ফাংশনে কী কী বস্তু রয়েছে তা যাচাই করতে ব্যবহার করতে পারি ।

    my_ellipsis_function <- function(...) {
        input_list <- list(...)
        output_list <- lapply(X=input_list, function(x) {str(x);summary(x)})
        return(output_list)
    }
    my_ellipsis_function(a=1:10,b=11:20,c=21:30)
     int [1:10] 1 2 3 4 5 6 7 8 9 10
     int [1:10] 11 12 13 14 15 16 17 18 19 20
     int [1:10] 21 22 23 24 25 26 27 28 29 30
    $a
       Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
       1.00    3.25    5.50    5.50    7.75   10.00 
    $b
       Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
       11.0    13.2    15.5    15.5    17.8    20.0 
    $c
       Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
       21.0    23.2    25.5    25.5    27.8    30.0 

    ঠিক আছে. আসুন substituteসংস্করণটি দেখুন:

       my_ellipsis_function <- function(...) {
           input_list <- as.list(substitute(list(...)))
           output_list <- lapply(X=input_list, function(x) {str(x);summary(x)})
           return(output_list)
       }
       my_ellipsis_function(a=1:10,b=11:20,c=21:30)
        symbol list
        language 1:10
        language 11:20
        language 21:30
       [[1]]
       Length  Class   Mode 
            1   name   name 
       $a
       Length  Class   Mode 
            3   call   call 
       $b
       Length  Class   Mode 
            3   call   call 
       $c
       Length  Class   Mode 
            3   call   call 

    আমাদের যা প্রয়োজন তা নয়। এই ধরণের অবজেক্টগুলি মোকাবেলার জন্য আপনার অতিরিক্ত কৌশলগুলি প্রয়োজন (যেমন রয়েছে write.csv)।

আপনি যদি ব্যবহার করতে চান ...তবে আপনার শ্যান উত্তরের মতো এটি ব্যবহার করা উচিত list(...)


38

আপনি এলিসিসকে এর সাথে তালিকায় রূপান্তর করতে পারেন list()এবং তারপরে আপনার ক্রিয়াকলাপ সম্পাদন করতে পারেন:

> test.func <- function(...) { lapply(list(...), class) }
> test.func(a="b", b=1)
$a
[1] "character"

$b
[1] "numeric"

সুতরাং আপনার get_list_from_ellipsisফাংশন ছাড়া আর কিছুই নয় list

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

অন্যথায়, আপনি যখন প্যারামিটারগুলির মাধ্যমে আপনার নিজের ফাংশন যুক্তিগুলিতে সমস্ত প্রকাশ না করে একটি সাবফংশনে পাস করতে চান তখন এটি ক্ষেত্রেও কার্যকর। এটি ফাংশন ডকুমেন্টেশনে লক্ষ করা যায়।


উপবৃত্তির পক্ষে আর্গুমেন্টের জন্য উপবৃত্তিকে পাস-থ্রো হিসাবে ব্যবহার করার বিষয়ে আমি জানি, তবে আর আদিমদের মধ্যে উপবৃত্তির পদ্ধতিটি যেমন আমি বর্ণনা করেছি সেভাবে ব্যবহার করাও প্রচলিত রীতি is প্রকৃতপক্ষে, উভয় listএবং cফাংশনগুলি এইভাবে কাজ করে তবে উভয়ই আদিম, সুতরাং তারা কীভাবে কাজ করে তা বুঝতে আমি সহজেই তাদের উত্স কোডটি পরীক্ষা করতে পারি না।
রায়ান সি থম্পসন

rbind.data.frameএইভাবে ব্যবহার করুন।
মারেক

5
যদি list(...)যথেষ্ট হয় তবে আর বিল্টিনগুলি কেন এর পরিবর্তে data.frameলম্বা ফর্মটি as.list(substitute(list(...)))[-1L]ব্যবহার করে?
রায়ান সি থম্পসন

1
আমি সৃষ্টি করিনি data.frame, আমি যে উত্তর জানি না (যে বললেন, আমি নিশ্চিত যে সেখানে আছি হয় এটির জন্য একটি ভাল কারণ)। আমি list()এই উদ্দেশ্যে নিজের প্যাকেজগুলিতে ব্যবহার করি এবং এখনও এটির সাথে কোনও সমস্যার মুখোমুখি হতে পারি না।
শেন

34

কেবল শেন এবং ডার্কের প্রতিক্রিয়াগুলিতে যুক্ত করার জন্য: এটির তুলনা করা আকর্ষণীয়

get_list_from_ellipsis1 <- function(...)
{
  list(...)
}
get_list_from_ellipsis1(a = 1:10, b = 2:20) # returns a list of integer vectors

$a
 [1]  1  2  3  4  5  6  7  8  9 10

$b
 [1]  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20

সঙ্গে

get_list_from_ellipsis2 <- function(...)
{
  as.list(substitute(list(...)))[-1L]
}
get_list_from_ellipsis2(a = 1:10, b = 2:20) # returns a list of calls

$a
1:10

$b
2:20

এটি যেমন দাঁড়িয়েছে তেমন কোনও সংস্করণ আপনার লক্ষ্যের জন্য উপযুক্ত বলে মনে হচ্ছে my_ellipsis_function, যদিও প্রথমটি পরিষ্কারভাবে সহজ।


15

আপনি ইতিমধ্যে অর্ধেক উত্তর দিয়েছেন। বিবেচনা

R> my_ellipsis_function <- function(...) {
+   input_list <- as.list(substitute(list(...)))
+ }
R> print(my_ellipsis_function(a=1:10, b=2:20))
[[1]]
list

$a
1:10

$b
11:20

R> 

সুতরাং এটি দুটি যুক্তি aএবং bকল থেকে গ্রহণ করে এটিকে একটি তালিকায় রূপান্তরিত করে। আপনি যা চেয়েছিলেন তা কি ছিল না?


2
আমি যা চাই তা পুরোপুরি নয়। এটি প্রকৃতপক্ষে তালিকার একটি তালিকা ফিরে আসে। লক্ষ্য করুন [[1]]। এছাড়াও, আমি জানতে চাই যে কীভাবে যাদু জাগরণ as.list(substitute(list(...)))কাজ করে।
রায়ান সি থম্পসন

2
অভ্যন্তরটি আর্গুমেন্টের উপর ভিত্তি list(...)করে একটি listবস্তু তৈরি করে। তারপরে substitute()অমূল্য অভিব্যক্তির জন্য পার্স গাছ তৈরি করে; এই ফাংশনটির জন্য সহায়তা দেখুন। পাশাপাশি একটি ভাল উন্নত পাঠ্য (বা এস)। এটি তুচ্ছ জিনিস নয়।
ডার্ক এডেলবুয়েটেল

ঠিক আছে, [[-1L]]অংশ সম্পর্কে (আমার প্রশ্ন থেকে) কী হবে? এটা করা উচিত নয় [[1]]?
রায়ান সি থম্পসন

3
আপনাকে ইনডেক্সে পড়তে হবে। বিয়োগের অর্থ 'বাদ দেওয়া', অর্থাত print(c(1:3)[-1])কেবল 2 এবং 3 মুদ্রণ করবে। Lএটি একটি পূর্ণসংখ্যা হিসাবে শেষ পর্যন্ত, এই আর সূত্র অনেক সম্পন্ন করা হয় তা নিশ্চিত করার জন্য একটি অত্যাধুনিক উপায়।
ডিস্ক এডেলবুয়েটেল

7
আমাকে সূচিকাগুলি পড়তে হবে না , তবে আপনি যে কমান্ডগুলি দেখিয়েছেন তার আউটপুটটিতে আমার খুব বেশি মনোযোগ দেওয়া দরকার। মধ্যে পার্থক্য [[1]]এবং $aসূচকের আমাকে কি মনে করে যে নেস্টেড তালিকা জড়িত ছিল প্রণীত। তবে এখন আমি দেখতে পাচ্ছি যে আপনি যা যা বাস্তবে পাবেন তা হ'ল আমি চাই তালিকাটি, তবে সামনে একটি অতিরিক্ত উপাদান রয়েছে। সুতরাং তারপর [-1L]বুদ্ধিমান। সেই অতিরিক্ত প্রথম উপাদানটি কোথা থেকে এসেছে? এবং সরল পরিবর্তে আমার এটি ব্যবহার করার কোনও কারণ আছে list(...)?
রায়ান সি থম্পসন

6

এটি প্রত্যাশার মতো কাজ করে। নিম্নলিখিতটি একটি ইন্টারেক্টিভ সেশন:

> talk <- function(func, msg, ...){
+     func(msg, ...);
+ }
> talk(cat, c("this", "is", "a","message."), sep=":")
this:is:a:message.
> 

একই, একটি ডিফল্ট যুক্তি ছাড়া:

> talk <- function(func, msg=c("Hello","World!"), ...){
+     func(msg, ...);
+ }
> talk(cat,sep=":")
Hello:World!
> talk(cat,sep=",", fill=1)
Hello,
World!
>

যেমন আপনি দেখতে পাচ্ছেন, ডিফল্টগুলি কোনও বিশেষ ক্ষেত্রে আপনি যা চান তা যদি না হয় তবে আপনি আপনার ফাংশনটির মধ্যে কোনও ফাংশনে 'অতিরিক্ত' যুক্তিগুলি পাস করতে এটি ব্যবহার করতে পারেন।

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