কীভাবে ifelse () তারিখের অবজেক্টগুলিকে সংখ্যাযুক্ত বস্তুতে পরিণত করা থেকে রোধ করবেন


161

আমি ifelse()একটি তারিখ ভেক্টর পরিচালনা করতে ফাংশনটি ব্যবহার করছি । আমি ফলাফলটি ক্লাসের হতে পারে বলে আশা করেছি Dateএবং numericপরিবর্তে ভেক্টর পেয়ে অবাক হয়েছি । এখানে একটি উদাহরণ:

dates <- as.Date(c('2011-01-01', '2011-01-02', '2011-01-03', '2011-01-04', '2011-01-05'))
dates <- ifelse(dates == '2011-01-01', dates - 1, dates)
str(dates)

এটি বিশেষত অবাক হওয়ার কারণ পুরো ভেক্টর জুড়ে অপারেশন করা কোনও Dateবস্তু ফেরায়।

dates <- as.Date(c('2011-01-01', '2011-01-02', '2011-01-03', '2011-01-04','2011-01-05'))
dates <- dates - 1
str(dates)

Dateভেক্টরগুলিতে চালনার জন্য আমার কি অন্য কোনও ফাংশন ব্যবহার করা উচিত ? যদি তাই হয়, কোন কাজ? যদি তা না হয় তবে কীভাবে আমি ifelseইনপুট হিসাবে একই ধরণের ভেক্টরকে ফেরত দিতে বাধ্য করব ?

সহায়তার পৃষ্ঠাটি ifelseইঙ্গিত দেয় যে এটি কোনও বৈশিষ্ট্য, কোনও বাগ নয়, তবে আমি এখনও অবাক হওয়ার মতো আচরণ বলে মনে করেছি তার ব্যাখ্যা খুঁজে পেতে লড়াই করছি।


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

উত্তর:


132

আপনি data.table::fifelse( data.table >= 1.12.3) বা ব্যবহার করতে পারেন dplyr::if_else


data.table::fifelse

বিপরীতে ifelse, fifelseইনপুটগুলির ধরণ এবং শ্রেণি সংরক্ষণ করে।

library(data.table)
dates <- fifelse(dates == '2011-01-01', dates - 1, dates)
str(dates)
# Date[1:5], format: "2010-12-31" "2011-01-02" "2011-01-03" "2011-01-04" "2011-01-05"

dplyr::if_else

dplyr 0.5.0প্রকাশের নোটগুলি থেকে :

[ if_else] এর কঠোর শব্দার্থক শব্দ রয়েছে যা ifelse(): trueএবং falseআর্গুমেন্টগুলি একই ধরণের হতে হবে। এটি কম আশ্চর্যজনক রিটার্ন টাইপ দেয় এবং এস 3 ভেক্টরকে তারিখের মতো সংরক্ষণ করে "।

library(dplyr)
dates <- if_else(dates == '2011-01-01', dates - 1, dates)
str(dates)
# Date[1:5], format: "2010-12-31" "2011-01-02" "2011-01-03" "2011-01-04" "2011-01-05" 

2
এটি আমাকে চেকমার্কটি looseিলে .ালা করে দিলে অবশ্যই অবশ্যই কার্যকর useful সহায়তা পৃষ্ঠার বর্তমান সংস্করণটি ফ্যাক্টর আর্গুমেন্ট থেকে কী আশা করবে তা বলে না। আমার ভোটটি এমন একটি ফ্যাক্টর রিটার্ন অবজেক্টের পক্ষে হবে যেখানে এর স্তরগুলি ছিল যেগুলি trueএর এবং falseএর স্তরের স্তরের মিলন ।
আইআরটিএফএম

3
if_elseএনএ হতে পারে আর্গুমেন্টগুলির একটি থাকার উপায় আছে কি ? আমি যৌক্তিক NA_বিকল্পগুলি চেষ্টা করেছি এবং কিছুই NA_double_
স্টিক

11
@ জাক ওয়ান সম্ভাবনাটি গুটিয়ে NAরাখা as.Date
হেনরিক

নেই NA_real_@roarkz। এবং @ হেনরিক, আপনার মন্তব্য এখানে আমার সমস্যার সমাধান করেছে।
বিএলটি

63

এটা তোলে নথিভুক্ত সম্পর্কিত মূল্য এর ifelse:

একই দৈর্ঘ্য এবং বৈশিষ্ট্যাবলী (মাত্রা এবং "সহ একটি ভেক্টর classযেমন") testএবং ডেটা মূল্যবোধের মান থেকে yesবা no। উত্তর মোড প্রথম কোনো মান থেকে নেওয়া মিটমাট যৌক্তিক থেকে বাধ্য করা হবে yesএবং তারপর কোনো মান থেকে নেওয়া no

এর প্রভাবগুলিতে সিদ্ধ হয়ে যায়, ifelseকারণগুলির স্তরগুলি হারাবে এবং তারিখগুলি তাদের শ্রেণি হারাবে এবং কেবলমাত্র তাদের মোড ("সংখ্যাসূচক") পুনরুদ্ধার করা হবে। পরিবর্তে এটি চেষ্টা করুন:

dates[dates == '2011-01-01'] <- dates[dates == '2011-01-01'] - 1
str(dates)
# Date[1:5], format: "2010-12-31" "2011-01-02" "2011-01-03" "2011-01-04" "2011-01-05"

আপনি এটি তৈরি করতে পারেন safe.ifelse:

safe.ifelse <- function(cond, yes, no){ class.y <- class(yes)
                                  X <- ifelse(cond, yes, no)
                                  class(X) <- class.y; return(X)}

safe.ifelse(dates == '2011-01-01', dates - 1, dates)
# [1] "2010-12-31" "2011-01-02" "2011-01-03" "2011-01-04" "2011-01-05"

পরবর্তী নোট: আমি দেখতে পাচ্ছি যে হ্যাডলি if_elseডেটা শেপিং প্যাকেজগুলির ম্যাজিটার / ডিপিপ্লায়ার / টিডায়ার কমপ্লেক্সে একটি তৈরি করেছে ।


37
কিছুটা আরও মার্জিত সংস্করণ:safe.ifelse <- function(cond, yes, no) structure(ifelse(cond, yes, no), class = class(yes))
হ্যাডলি

5
খুশী হলাম। ডিফল্ট আচরণ না হওয়ার কোনও কারণ কি আপনি দেখতে পাচ্ছেন?
আইআরটিএফএম

আপনি "হ্যাঁ" এ কী রেখেছেন তা যত্নবান হোন কারণ আমার কাছে এনএ ছিল এবং এটি কার্যকর হয়নি। প্যারামিটার হিসাবে ক্লাসটি পাস করার চেয়ে সম্ভবত এটি "হ্যাঁ" শর্তের শ্রেণি হিসাবে ভাল।
ডেনিস

1
আমি নিশ্চিত নই যে শেষ মন্তব্যটির অর্থ এটি। যেহেতু কোনও কিছুর একটি এনএ মান রয়েছে তার অর্থ এটির ক্লাস থাকতে পারে না।
আইআরটিএফএম

8 বছর থেকে এই সমস্যা আসা পর্যন্ত এবং এখনও করেছে ifelse()নয় "নিরাপদ"
এম-- 14'19

16

ডিউইন এর ব্যাখ্যা স্পট হয়। আমি ইফিলস বিবৃতি দেওয়ার পরে ক্লাসটিকে কেবল জোর করে ফেলতে পারার আগে আমি বুঝতে পেরেছিলাম এবং এটির সাথে লড়াই করেছি কিছু সময়ের জন্য:

dates <- as.Date(c('2011-01-01','2011-01-02','2011-01-03','2011-01-04','2011-01-05'))
dates <- ifelse(dates=='2011-01-01',dates-1,dates)
str(dates)
class(dates)<- "Date"
str(dates)

প্রথমে এটি আমার কাছে কিছুটা "হ্যাকিশ" অনুভূত হয়েছিল। তবে এখন আমি এটিকে আইফেলস () থেকে প্রাপ্ত পারফরম্যান্স রিটার্নের জন্য অর্থ প্রদানের জন্য একটি ছোট দাম হিসাবে মনে করি। এছাড়াও এটি একটি লুপের চেয়ে অনেক বেশি সংক্ষিপ্ত।


এই (চমৎকার, যদি, হ্যাঁ, hackish) টেকনিক এছাড়াও আসলে সাহায্যের মনে হচ্ছে যে আর এর forবিবৃতি নির্ধারণ মান আইটেমগুলির VECTORকরতে NAME, কিন্তু না তাদের বর্গ
গ্রেগ মিনশাল

6

প্রস্তাবিত পদ্ধতিটি ফ্যাক্টর কলামগুলির সাথে কাজ করে না। আইডি এই উন্নতির পরামর্শ দিতে চাই:

safe.ifelse <- function(cond, yes, no) {
  class.y <- class(yes)
  if (class.y == "factor") {
    levels.y = levels(yes)
  }
  X <- ifelse(cond,yes,no)
  if (class.y == "factor") {
    X = as.factor(X)
    levels(X) = levels.y
  } else {
    class(X) <- class.y
  }
  return(X)
}

উপায় দ্বারা: ifelse সফল হয় ... মহান ক্ষমতা সঙ্গে মহান দায়িত্ব আসে, অর্থাত 1x1 ম্যাট্রিক এবং / বা সংখ্যার টাইপ রূপান্তর [যখন তারা উদাহরণ হিসাবে যুক্ত করা উচিত] আমার কাছে ঠিক আছে তবে ifelse এ এই ধরণের রূপান্তরটি স্পষ্টভাবে অযাচিত। আমি এখন একাধিকবার ইফলেসের খুব একই 'বাগ' এ umpুকেছি এবং এটি আমার সময় চুরি করে চলেছে :-(

ফাঃ


এটি একমাত্র সমাধান যা আমার জন্য কারণগুলির জন্য কাজ করে।
bshor

আমি চিন্তা করে যে স্তরের স্তরের ইউনিয়ন হবে ফেরত পাঠাবে yesএবং noএবং আপনি প্রথম দেখতে তারা উভয় কারণের ছিল পরীক্ষা হবে। আপনাকে সম্ভবত চরিত্রায় রূপান্তর করতে হবে এবং তারপরে "ইউনিয়নাইজড"-লেভেলগুলির সাথে পুনর্বিবেচনা করতে হবে।
আইআরটিএফএম

6

এটি কাজ না করার কারণ হ'ল, ifelse () ফাংশনটি মানগুলিকে ফ্যাক্টারে রূপান্তর করে। এটির মূল্যায়নের আগে এটি অক্ষরে রূপান্তর করা একটি দুর্দান্ত কাজ।

dates <- as.Date(c('2011-01-01','2011-01-02','2011-01-03','2011-01-04','2011-01-05'))
dates_new <- dates - 1
dates <- as.Date(ifelse(dates =='2011-01-01',as.character(dates_new),as.character(dates)))

এর জন্য বেস আর ব্যতীত আর কোনও লাইব্রেরি লাগবে না


5

@ ফ্যাবিয়ান-ওয়ার্নারের সরবরাহকৃত উত্তরটি দুর্দান্ত, তবে বস্তুগুলির একাধিক শ্রেণি থাকতে পারে এবং "ফ্যাক্টর" অগত্যা প্রথম class(yes)পাঠানো হতে পারে না , তাই সমস্ত শ্রেণীর বৈশিষ্ট্যগুলি পরীক্ষা করার জন্য আমি এই ছোট্ট পরিবর্তনটি প্রস্তাব করছি:

safe.ifelse <- function(cond, yes, no) {
      class.y <- class(yes)
      if ("factor" %in% class.y) {  # Note the small condition change here
        levels.y = levels(yes)
      }
      X <- ifelse(cond,yes,no)
      if ("factor" %in% class.y) {  # Note the small condition change here
        X = as.factor(X)
        levels(X) = levels.y
      } else {
        class(X) <- class.y
      }
      return(X)
    }

আমি আর ডাব্লু ডেভেলপমেন্ট টিমের কাছে একটি অনুরোধ জমা দিয়েছি যাতে বেস :: আইফেলস () ব্যবহারের জন্য কোন বৈশিষ্ট্যগুলি সংরক্ষণ করতে হবে তার ব্যবহারকারী নির্বাচনের উপর ভিত্তি করে বৈশিষ্ট্যগুলি সংরক্ষণ করতে ডকুমেন্টেড বিকল্প যুক্ত করতে হবে। অনুরোধটি এখানে রয়েছে: https://bugs.r-project.org/bugzilla/show_bug.cgi?id=16609 - এটি ইতিমধ্যে যেভাবে আগে থেকে চলেছে এই কারণেই এটি ইতিমধ্যে "WONTFIX" হিসাবে চিহ্নিত করা হয়েছে, তবে আমি কেন একটি সাধারণ সংযোজন R এর প্রচুর ব্যবহারকারীর মাথাব্যথা বাঁচাতে পারে তার একটি ফলো-আপ যুক্তি সরবরাহ করেছি। সম্ভবত আপনার "+1" বাগ বাগের থ্রেডটি আর কোর টিমকে দ্বিতীয় দর্শন নিতে উত্সাহিত করবে।

সম্পাদনা: এখানে একটি আরও ভাল সংস্করণ যা ব্যবহারকারীকে "কনড" (ডিফল্ট ifelse () আচরণ), "হ্যাঁ", উপরের কোড অনুসারে আচরণ, বা "না", ক্ষেত্রে যে বৈশিষ্ট্যগুলি সংরক্ষণ করতে হবে তা নির্দিষ্ট করার অনুমতি দেয় the "না" মানের বৈশিষ্ট্য আরও ভাল:

safe_ifelse <- function(cond, yes, no, preserved_attributes = "yes") {
    # Capture the user's choice for which attributes to preserve in return value
    preserved           <- switch(EXPR = preserved_attributes, "cond" = cond,
                                                               "yes"  = yes,
                                                               "no"   = no);
    # Preserve the desired values and check if object is a factor
    preserved_class     <- class(preserved);
    preserved_levels    <- levels(preserved);
    preserved_is_factor <- "factor" %in% preserved_class;

    # We have to use base::ifelse() for its vectorized properties
    # If we do our own if() {} else {}, then it will only work on first variable in a list
    return_obj <- ifelse(cond, yes, no);

    # If the object whose attributes we want to retain is a factor
    # Typecast the return object as.factor()
    # Set its levels()
    # Then check to see if it's also one or more classes in addition to "factor"
    # If so, set the classes, which will preserve "factor" too
    if (preserved_is_factor) {
        return_obj          <- as.factor(return_obj);
        levels(return_obj)  <- preserved_levels;
        if (length(preserved_class) > 1) {
          class(return_obj) <- preserved_class;
        }
    }
    # In all cases we want to preserve the class of the chosen object, so set it here
    else {
        class(return_obj)   <- preserved_class;
    }
    return(return_obj);

} # End safe_ifelse function

1
inherits(y, "factor")"factor" %in% class.y
আইআরটিএফএম

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