مسیر
/
R
R
/
برنامه‌ی درسی
/
فیلترکردن بردار
فی

فیلترکردن بردار در R

3 تمرین

درباره‌ی فیلترکردن بردار

در مفهوم Vectors دیدیم که یک بردار می‌تواند در یک عبارت شرطی استفاده شود و یک بردار منطقی بدهد. این به نوبه‌ی خود می‌تواند در توابعی مانند all() و any() استفاده شود.

v <- c(4, 7, 10)
v >= 6
#> [1] FALSE  TRUE  TRUE
all(v > 6)
#> [1] FALSE    # not all elements match this condition
any(v > 6)
#> [1] TRUE     # at least one element matches

این تکنیک بسیار قدرتمندتر از این است.

زیرمجموعه‌های بردار

عنصرهای انتخاب‌شده‌ی یک بردار را می‌توان با یک شماره‌ی اندیس یا برداری از اندیس‌ها بیرون کشید:

v <- 5:10
v
#> [1]  5  6  7  8  9 10
v[3] 
#> [1] 7
v[c(2, 4)]
#> [1] 6 8

در روشی دیگر، از یک بردار منطقی برای فیلتر کردن بردار اصلی استفاده کنید، که زیرمجموعه‌ای از عنصرهای متناظر با مقدار TRUE را برمی‌گرداند:

v <- 1:3
bools <- c(FALSE, TRUE, TRUE)
v[bools]
#> [1] 2 3

از آنجا تا تولید بردار منطقی با یک عبارت شرطی فاصله‌ی کمی است:

bools <- v >= 2
bools
#> [1] FALSE  TRUE  TRUE

v[bools]
#> [1] 2 3

# simpler form
v[v >= 2]
#> [1] 2 3

این عبارت‌های شرطی می‌توانند به‌طور دلخواه پیچیده باشند و چندین بردار یا تابع را درگیر کنند:

v <- 1:10
w <- 10:1

# pairwise comparison
v > w
#> [1] FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE

# shorter form
v[v > w]
#> [1]  6  7  8  9 10

نام‌گذاری

ما این مفهوم را «فیلتر کردن بردار» نامیدیم، به این امید که برای گسترده‌ترین طیف برنامه‌نویسان قابل‌فهم باشد.

در جامعه‌ی R، اصطلاح «Subsetting» احتمالاً رایج‌تر است.

بازیافت

برای سادگی، همه‌ی مثال‌های بالا بردارهایی با طول یکسان را مقایسه می‌کردند. اگر طول‌ها ناهماهنگ باشند چه اتفاقی می‌افتد؟

پاسخ چیزی است که اگر عمداً استفاده شود قدرتمند است، اما اگر ناخواسته پیش بیاید گیج‌کننده است.

یک مثال:

v <- 1:6
cond <- c(TRUE, FALSE)
v[cond]
#> [1] 1 3 5

چه اتفاقی افتاد؟ ما برداری با طول ۶ را با یک بردار منطقی به طول ۲ اندیس‌گذاری کردیم، اما در نتیجه برداری با طول ۳ به دست آوردیم.

اگر برداری به‌نوعی برای عبارتی که در آن استفاده می‌شود «بیش از حد کوتاه» باشد، R آن را تا رسیدن به طول موردنظر تکرار می‌کند: به این کار «بازیافت» می‌گویند. این کار بردار c(TRUE, FALSE) ما را به c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE) تبدیل کرد و سپس v[cond] مقادیر TRUE را از v برگرداند: در این مورد، اعداد فرد.

حالا در مثال بعدی چه اتفاقی می‌افتد؟

v <- 1:3
0.5 * v
#> [1] 0.5 1.0 1.5
2 + v
#> [1] 3 4 5

در نگاه اول شبیه ضرب اسکالر و (کمی عجیب) جمع اسکالر به نظر می‌رسد، اما در R اسکالر وجود ندارد.

در عوض، اعداد بازیافت می‌شوند تا برداری هم‌طول با v به دست آید، سپس عمل حسابی به‌صورت عنصربه‌عنصر با استفاده از c(0.5, 0.5, 0.5) یا c(2, 2, 2) اعمال می‌شود.

Caution

بازیافت بسیار بسیار مفید است، اما مطمئن شوید که منظورتان همین است.

کمی ناهماهنگی در طول بردارها (مثلاً ۹۹ در برابر ۱۰۰) می‌تواند Bugهای گیج‌کننده ایجاد کند.

بعضی از نویسندگان توصیه می‌کنند که بازیافت فقط وقتی استفاده شود که یکی از بردارها طول ۱ داشته باشد.

یافتن اندیس‌ها

تابع which() یک آرگومان منطقی می‌گیرد و برداری از اندیس‌ها را برمی‌گرداند که مقدار TRUE می‌دهند.

v
#> [1] 2 7 9

v[v > 5]  # returns values
#> [1]  7  9

which(v > 5) # returns indices
#> [1] 2 3

بررسی وجود یک عنصر

بخش‌های قبلی درباره‌ی یافتن عنصرهایی بود که با معیاری مطابقت دارند.

اگر فقط می‌خواهید بدانید که آیا بردار شامل عنصر مشخصی هست یا نه، از عملگر %in% استفاده می‌شود.

3 %in% 1:5
#> [1] TRUE
7 %in% 1:5
#> [1] FALSE

این از نظر عملکردی معادل کد زیر است، اما بسیار راحت‌تر:

length(v[v == 3]) > 0
#> [1] TRUE

عملگر %notin% هم وجود دارد که not منطقیِ %in% را می‌دهد.

ویرایش از طریق GitHub این پیوند در پنجره یا زبانه‌ی جدیدی باز می‌شود

فیلترکردن بردار را یاد بگیرید

تمرین کردن قفل شده است

برای تمرین فیلترکردن بردار قفل 2 تمرین دیگر را باز کنید