Использование векторизованных процедур: оператор ifelse

Рассмотрим достаточно частый случай, когда функция представляет собой две ветви, заданные по-разному, например:

Задание 6. Запрограммировать функциюW(x), заданную системой:

и построить ее график на отрезке .

 

Решение. На первый взгляд, задача для нас уже не представляет проблемы. Действительно, используя оператор if () {} else {} можно получить вполне корректный код функции:

W<- function(x) {# Объявление имени функции W(x)

if (x>= 0) {Res<- x^2} else{Res<- sin(2*x)} # Вычислениеправой и левой ветвей

return(Res)

}

W(2) # Возвращает 2^2 - правая ветвь

W(-pi/4) # Возвращает sin(-2pi/4) - левая ветвь

Однако, у этого кода есть существенный недостаток! Так написанная функция W(x) не будет воспринимать векторизованные обращения. Иными словами, привычным способом построить график этой функции нам не удастся: компилятор R выдаст ошибку на второй строчке кода при попытке подставить в функцию не число, а целый вектор:

x <- seq(-10,5,length.out = 101) # Разбиваем отрезок [-10; 5] на 100 частей

y <- W(x) # Вычисляем значения функции W(x) во всех точках

plot(x,y,type = "l",lwd = 2,col="blue") # Строимграфикy=W(x)

Дело в том, что в языке Rусловный операторif () {} else {} не работает с векторизованными величинами. Здесь необходимо использовать специальные конструкции.

Самой простой и понятной является схема с привлечением специального оператора ifelse (A, expr1,expr2), который при выполнении условия A, реализует действия, составленные в expr1, а при невыполнении условия A, соответственно – в expr2. В нашем случае функция будет запрограммирована так:

W<- function(x)

{

Res <- ifelse(x>=0,x^2,sin(2*x))

return(Res)

}

 

x<- seq(-10,5,length.out = 1001) # Разбиваем отрезок [-10; 5] на 1000 частей

y<- W(x) # Вычисляем значения функции W(x) во всех точках

plot(x,y,type = "l",lwd = 2,col="blue") # Строимграфик y=W(x)

Это позволяет построить график функции привычным образом с использованием векторизованных обращений к W(x)

 

Использование векторизованных процедур: оператор […]

 

Для построения функций, заданных по-разному на трех и более промежутках, вместо вложенных конструкций ifelse лучше использовать оператор квадратных скобок […] – самый мощный для векторизованных процедур.

Задание 7*. Запрограммировать в RфункциюS(x), заданную системой:

,

и построить ее график на отрезке .

Решение. Введем следующий код, задающий функцию S(x) на трех промежутках:

S<- function(x)

{

A<- (x<0) # Создаем массив из "TRUE/да" и "FALSE/нет" для x< 0

B<- (x>=0)&(x<=2) # Создаем массив из "TRUE/да" и "FALSE/нет" для (x>= 0) и (x<= 2)

D<- (x>2) # Создаем массив из "TRUE/да" и "FALSE/нет" для x> 2

x[A] <- sin(2*x[A]) # Вычисляем левую ветвь функции

x[B] <- x[B]^2 # Вычисляем середину функции

x[D] <- 6 - x[D] # Вычисляем правую ветвь функции

Res<- x

return(Res)

}

Идея здесь следующая: весь массив аргументов функции разделить на три группы A,B и D, в которых функция задана соответственно одной из трех ветвей. Здесь A– это массив из последовательности «да» и «нет». Если в каком-либо месте стоит «да», то на этом месте подходящий аргумент функции для левой ветви, если нет – неподходящий. Аналогично для B и D.

В следующих трех строках значения соответствующих аргументов x[A], x[B] и x[D] переопределяются в значения самой функции.

Теперь можно построить графикS(x):

x <- seq(-10,5,length.out = 1001) # Разбиваем отрезок [-10; 5] на 1000 частей

y <- S(x) # Вычисляем значения функции S(x) во всех точках

plot(x,y,type = "l",lwd = 2,col="red") # Строимграфик y=S(x)

abline(h = 0, v = 0, col = "gray40") # Рисуемосикоординат

 


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: