Пользовательская функция по разному обрабатывает значения и векторы

Вопросы по статистическому пакету R. Не обязательно гео.
Ответить
Аватара пользователя
VistaSV30
Активный участник
Сообщения: 185
Зарегистрирован: 02 июл 2018, 15:05
Репутация: 7
Откуда: Балашиха

Пользовательская функция по разному обрабатывает значения и векторы

Сообщение VistaSV30 » 16 июл 2020, 19:48

Добрый день!

У меня есть функция для вычисления прироста:

Код: Выделить всё

tr <- function(d1, d2){
  if (d1>0) s = round((d2 - d1) / d1 * 100, 1)
  if (s > 99.999) s = paste('\u2b\u432', round(d2 / d1, 1), '\u440\u430\u437\u430')
  return(s)
}
Отдельные значения функция вычисляет корректно, но с векторами такого не получается. Например,
> tr(2,7)
[1] "+в 3.5 раза"

А если использовать векторы в качестве аргументов, то не получается:

Код: Выделить всё

n1 <- sample(0:5, 10, replace = T)
n2 <- sample(0:5, 10, replace = T)

> n1
 [1] 3 5 4 1 3 1 0 0 2 5
> n2
 [1] 5 4 2 3 3 5 2 1 2 2
> tr(n1,n2)
 [1]  66.7 -20.0 -50.0 200.0   0.0 400.0   Inf   Inf   0.0 -60.0
Предупреждения:
1: В if (d1 > 0) s = round((d2 - d1)/d1 * 100, 1) :
  длина условия > 1, будет использован только первый элемент
2: В if (s > 99.999) s = paste("+в", round(d2/d1, 1), "раза") :
  длина условия > 1, будет использован только первый элемент
Может быть как-то по другому надо задавать условия?
Подскажите пожалуйста!
Природа не просто эксцентричнее, чем мы полагаем - она эксцентричнее, чем мы способны предположить. John Haldane

gamm
Гуру
Сообщения: 4047
Зарегистрирован: 15 окт 2010, 08:33
Репутация: 1050
Ваше звание: программист
Откуда: Казань

Re: Пользовательская функция по разному обрабатывает значения и векторы

Сообщение gamm » 16 июл 2020, 20:44

Там же зеленым по русски написано, что нельзя в условие вектор вставлять. Либо цикл, что медленно, либо векторизация: вычислить логический индекс (маску искомых элементов), и использовать ее для изменения. Уже проходили на одном из предыдущих занятий :mrgreen:

Аватара пользователя
VistaSV30
Активный участник
Сообщения: 185
Зарегистрирован: 02 июл 2018, 15:05
Репутация: 7
Откуда: Балашиха

Re: Пользовательская функция по разному обрабатывает значения и векторы

Сообщение VistaSV30 » 17 июл 2020, 09:02

Вот так теперь работает как надо:

Код: Выделить всё

 # Прирост
tr <- function(d1, d2, Percent = NULL ){
  s = round((d2 - d1) / d1 * 100, 1)
  s1 <- s
  s2 <- paste('\u2b\u432', sprintf("%1.1f", d2 / d1), '\u440\u430\u437\u430')
  s1[s == 0] <- '\u443\u440\u43e\u432\u2e'
  s1[s == -100] <- "-"
  s1[s >= 100] <- s2[s >= 100]
  s1[is.infinite(s) == TRUE] <- "+"
  return(s1)
}
Сейчас еще придумаю как знак % добавлять
Последний раз редактировалось VistaSV30 17 июл 2020, 09:52, всего редактировалось 1 раз.
Природа не просто эксцентричнее, чем мы полагаем - она эксцентричнее, чем мы способны предположить. John Haldane

gamm
Гуру
Сообщения: 4047
Зарегистрирован: 15 окт 2010, 08:33
Репутация: 1050
Ваше звание: программист
Откуда: Казань

Re: Пользовательская функция по разному обрабатывает значения и векторы

Сообщение gamm » 17 июл 2020, 09:15

VistaSV30 писал(а):
17 июл 2020, 09:02
То есть, сначала нужно создать вектор из результатов вычислений, а потом функцией which() искать значения по условиям?
нет, вас все время на последовательную обработку тянет. Нужно векторизовать. Уже делали, примерно так

Код: Выделить всё

s<-rep("-",length(d1))
s[d1 == d2] = "уровень"
s[d1 == 0 && d2 == 0] = "-"
s[d1 == 0 && d2 > ] = "+"
s[d1 > 0 && d2 == 0] = "-"

Аватара пользователя
VistaSV30
Активный участник
Сообщения: 185
Зарегистрирован: 02 июл 2018, 15:05
Репутация: 7
Откуда: Балашиха

Re: Пользовательская функция по разному обрабатывает значения и векторы

Сообщение VistaSV30 » 17 июл 2020, 09:54

Ой!
Пока исправлял свой вопрос мне уже ответили.

По-моему, теперь сделал как надо. (Если Percent != NULL, то к результату добавляется знак %)

Код: Выделить всё

# Прирост
tr <- function(d1, d2, Percent = NULL ){
  s = round((d2 - d1) / d1 * 100, 1)
  s1 <- s
  s2 <- paste('\u2b\u432', sprintf("%1.1f", d2 / d1), '\u440\u430\u437\u430')
  s1[s == -100] <- "-"
    d1[d1 == 0] <- 1e-10
  s1[(d2/d1)>=2] <- s2[(d2/d1)>=2]
  s1[is.infinite(s) == TRUE] <- "+"
  s1[is.na(s) == TRUE] <- "-"
  s2 <- paste0(s,"%")
  s1[abs(s) < 100 & is.null(Percent) == FALSE] <- s2[abs(s) < 100]
  s1[s == 0] <- '\u443\u440\u43e\u432\u2e'
return(s1)
}
Последний раз редактировалось VistaSV30 17 июл 2020, 14:22, всего редактировалось 3 раза.
Природа не просто эксцентричнее, чем мы полагаем - она эксцентричнее, чем мы способны предположить. John Haldane

nickleb
Гуру
Сообщения: 964
Зарегистрирован: 22 май 2010, 20:20
Репутация: 154

Re: Пользовательская функция по разному обрабатывает значения и векторы

Сообщение nickleb » 17 июл 2020, 10:24

Код: Выделить всё

TR <- sapply(seq_along(n1), 
             function (i) {tr(n1[i], n2[i])})

nickleb
Гуру
Сообщения: 964
Зарегистрирован: 22 май 2010, 20:20
Репутация: 154

Re: Пользовательская функция по разному обрабатывает значения и векторы

Сообщение nickleb » 17 июл 2020, 10:42

... или через purrr :

Код: Выделить всё

TR <- purrr::map2_chr(n1, n2, tr)

nickleb
Гуру
Сообщения: 964
Зарегистрирован: 22 май 2010, 20:20
Репутация: 154

Re: Пользовательская функция по разному обрабатывает значения и векторы

Сообщение nickleb » 17 июл 2020, 11:02

VistaSV30 писал(а):
16 июл 2020, 19:48
Отдельные значения
... а "отдельные значения" - в Вашем контексте - так это скаляры, которые по R-сути являются векторами длинной единица

Аватара пользователя
VistaSV30
Активный участник
Сообщения: 185
Зарегистрирован: 02 июл 2018, 15:05
Репутация: 7
Откуда: Балашиха

Re: Пользовательская функция по разному обрабатывает значения и векторы

Сообщение VistaSV30 » 17 июл 2020, 11:03

Решил все-таки использовать свой вариант функции, сделанный по советам gamm.
Поскольку в итоге планирую все функции собрать в один пакет.

Спасибо еще раз!
Природа не просто эксцентричнее, чем мы полагаем - она эксцентричнее, чем мы способны предположить. John Haldane

Ответить

Вернуться в «R»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 6 гостей