R-এ অপারেটরের একটি সেট আছে, যা অন্য অনেক ভাষার মতোই:
1 == 2 # FALSE
1 != 2 # TRUE
1 < 2 # TRUE
1 > 2 # FALSE
1 <= 2 # TRUE
1 >= 2 # FALSE
if-then-else-এর মূল রূপটি হলো:
if (x > 10) {
y <- "big"
} else if (x > 2) {
y <- "medium"
} else {
y <- "tiny"
}
এই ক্ষেত্রে বুলিয়ানটির চারপাশে প্রথম বন্ধনী ( ) এবং বডির চারপাশে দ্বিতীয় বন্ধনী { }, দুটোই আবশ্যক।
সহজ if স্টেটমেন্ট সংক্ষিপ্ত করা যায়:
if (x == 0) return("success")
সামনে থাকা vector-filtering কনসেপ্টের প্রসঙ্গে: প্রথম বন্ধনী ()-এর ভেতরের কন্ডিশনাল ক্লজটি অবশ্যই একটি একক TRUE/FALSE মানে মূল্যায়িত হতে হবে।
তুলনায় ভেক্টর যোগ করলে সাধারণত বুলিয়ানের একটি ভেক্টর পাওয়া যায়, তাই এগুলোকে all() (সব মান কি TRUE?) বা any() (অন্তত একটি মান কি TRUE?) এর মতো একটি অ্যাগ্রিগেটিং ফাংশনের ভেতরে মুড়ে দিতে হবে।
numbers <- c(4,5,7,9,10,11)
numbers %% 3 == 0 # gives vector of booleans
#> [1] FALSE FALSE FALSE TRUE FALSE FALSE
# use any() to get a single TRUE/FALSE
if (any(numbers %% 3 == 0)) print("1 or more numbers are divisible by 3")
#> [1] "1 or more numbers are divisible by 3"
ifelse ফাংশনবিকল্প একটি if-else রূপ কাজে লাগতে পারে, যদি ফলাফল কেবল ট্রু/ফলস হয়।
y <- ifelse(x > 8, "big", "small")
# Don't mix result types:
z <- ifelse(x > 100, 100, "small") # numeric or string result? Expect problems!
ifelse() ঠিক তিনটি প্যারামিটার নেয়:
TRUE হলে যে মানFALSE হলে যে মান।ভেক্টর ইনপুটও গ্রহণযোগ্য, আর তখন আউটপুটও একটি ভেক্টর হয়।
এই ক্ষেত্রে নিশ্চিত করুন যে দুই ব্রাঞ্চের ফলাফল একই ডেটা টাইপে হয়: নিউমেরিক, ক্যারেক্টার, লজিক্যাল ইত্যাদি।
এটি vector-functions কনসেপ্টে আলোচনা করা হবে।
দুইটি ফলাফল (উপরের উদাহরণে "big", "small") একক মান হওয়া উচিত।
দুর্ভাগ্যবশত, এখানে আরও লম্বা কোনো ভেক্টর দিলে R সম্ভবত বিভ্রান্তিকর ও অপ্রত্যাশিত কিছু করবে, অথচ কোনো ওয়ার্নিং মেসেজ দেবে না।
if_else ফাংশনR ভাষার রক্ষণাবেক্ষণকারীরা যতটা সম্ভব ব্রেকিং চেঞ্জ এড়িয়ে চলার নীতি অনুসরণ করে। এটি CRAN-এ থাকা বিপুল সংখ্যক থার্ড-পার্টি প্যাকেজ রক্ষণাবেক্ষণে সাহায্য করে, তবে আধুনিক প্রোগ্রামিং কনসেপ্ট দিয়ে base R আপডেট করার সক্ষমতাকে সীমিত করে।
সাম্প্রতিক বছরগুলোতে এমন বেশ কিছু প্যাকেজ প্রকাশিত হয়েছে, যেগুলো R-এর কার্যকারিতা বাড়ায় এবং কখনো কখনো তা প্রতিস্থাপন করে; মূল R ডিজাইনের শক্তি ও দুর্বলতা নিয়ে কয়েক দশকের অভিজ্ঞতার ভিত্তিতে এসব তৈরি।
এই প্যাকেজগুলো মিলে tidyverse সংগ্রহটি গঠন করে।
২০২৩ সালে এগুলো Exercism টেস্ট রানারে যুক্ত করা হয়, আর অনুশীলনীতে ব্যবহারের জন্য আপনার জন্যও উপলব্ধ।
আমাদের R ট্র্যাক tidyverse যুক্ত হওয়ার কয়েক বছর আগে থেকেই আছে, তাই হয়তো আপনি লক্ষ্য করবেন যে অনেক কমিউনিটি সলিউশন base ভাষাতেই সীমাবদ্ধ থাকে।
dplyr প্যাকেজdplyr মূলত ডেটাফ্রেম ম্যানিপুলেশন নিয়ে কাজ করে (কোর্সের পরে আলোচনা করা হবে)।
কোডের শুরুতে library(dplyr) দিয়ে অথবা পুরো সংগ্রহটি যোগ করতে library(tidyverse) দিয়ে এটি যুক্ত করুন।
মাস্ক করা নাম নিয়ে ওয়ার্নিং মেসেজ দেখতে পারেন, তবে এটি খুব একটা সমস্যা নয়।
বর্তমান কনসেপ্টে if_else ফাংশনটি উল্লেখ করার মতো।
এটি base R-এর ifelse ফাংশনের সাথে অনেকটাই মিল।
library(dplyr) # warnings not shown
x <- 10
if_else(x > 8, "big", "small")
#> [1] "big"
মূল পার্থক্য হলো, if_else চাইলে একটি ঐচ্ছিক চতুর্থ আর্গুমেন্ট নিতে পারে, যেটি অনুপস্থিত মানের জন্য, আর R-এ এগুলো NA দিয়ে প্রকাশ করা হয়।
xs <- c(3, NA, 10, NA, 4) # a 5-element vector
xs
#> [1] 3 NA 10 NA 4
if_else(xs > 8, "big", "small", "missing")
#> [1] "small" "missing" "big" "missing" "small"
# contrast:
ifelse(xs > 8, "big", "small")
#> [1] "small" NA "big" NA "small"
আপনি আরও দেখবেন, পুরোনো ifelse-এর চেয়ে if_else-এর এরর মেসেজ অনেক ভালো।
dplyr লাইব্রেরি লোড করার পর, between() ফাংশনটিও আপনার হাতে থাকবে।
R তুলনার চেইনিং করতে দেয় না, তাই 1 <= x <= 5 লিখলে এরর মেসেজ আসবে।
dplyr লোড করা থাকলে, between(x, 1, 5) হলো x >= 1 & x <= 5-এর সমতুল্য, আর সম্ভবত আরও পাঠযোগ্য।
নিম্ন ও ঊর্ধ্ব, উভয় সীমাই অন্তর্ভুক্ত।