2017-02-04 3 views
1

Я пытаюсь написать функцию, которая заменит значение в векторе тем же значением, разделенным на два.Замена отрицательного значения в df для одного и того же значения, деленного на два

# replacement function for a vector 
rep <- function(x) 
    x.half <- {abs(replace(x, which(x<0),x/2))} 

Но, я знаю, что эта функция не работает должным образом, потому что если я моделировать вектор с отрицательными и положительными числами я получаю неправильный результат:

a <- c(1,-1,2,-2,3,-3,4,-4,5,-5,11,-11,12,-12,13,-13,21,-21,25,-25) 
a.rep <- rep(a) 

# data frame to test 
test <- cbind(a,a.rep) 

Кроме того, когда я применяю эту функцию вектор а, я получаю предупреждение, как это:

Предупреждение сообщение: в заменить (х, что (х < 0), х/2): количество элементов, чтобы заменить это не кратна замещающей длине

Очевидно, что что-то не так с моей функцией.

+1

Это очень короткая версия моей функции, что хорошо. Но мне нужно уменьшить вдвое отрицательные значения, все положительные значения не должны быть изменены. – marianess

+0

'a [which (a <1)] = a [which (a <1)]/2' Это будет работать, нет необходимости писать функцию для этого. –

+0

Только что понял, что это лучший и самый короткий ответ: D Спасибо @ChirayuChamoli – marianess

ответ

5

Третий аргумент в replace должен быть такой же длины, как и значения будучи subsetted во втором.

## determine which values are below zero 
a0 <- a < 0 
## replace them with their halved values 
replace(a, a0, a[a0]/2) 
[1] 1.0 -0.5 2.0 -1.0 3.0 -1.5 4.0 -2.0 5.0 -2.5 11.0 
[12] -5.5 12.0 -6.0 13.0 -6.5 21.0 -10.5 25.0 -12.5 
4

можно использовать ifelse():

half_if_neg <- function(x) {ifelse(x < 0, x/2, x)} 
#sapply(a, half_if_neg) 
half_if_neg(a) 
+1

'ifelse' векторизован, поэтому нужно' sapply() ' –

+0

очень верно, отредактировано – Nate

2

Мы также можем выполнить задание

i1 <- a < 0 
a[i1] <- a[i1]/2 

Или с помощью

pmax(a, (a*NA^(a >=0))/2, na.rm = TRUE) 
#[1] 1.0 -0.5 2.0 -1.0 3.0 -1.5 4.0 -2.0 5.0 -2.5 11.0 
#[12] -5.5 12.0 -6.0 13.0 -6.5 21.0 -10.5 25.0 -12.5 
+0

@RichScriven Это альтернативный подход. Я считаю, что ваш метод 'replace' также очень оригинален. – akrun

+0

@RichScriven Я не нашел никого, кто использовал бы это в ответе. Если вы говорите о комментариях, извините, я не проверял комментарии. Во всяком случае, я также добавил альтернативный подход, который является очень оригинальным, как хорошо – akrun

+0

@RichScriven BTW, вы не думаете, что это будет иметь шанс на обман, не так ли? – akrun

5

Хотя вопрос был дан ответ уже, я почувствовал вызов, чтобы добавить арифметическое решение.

Выражение

(sign(a) + 3)/4 * a 

вернется

# [1] 1.0 -0.5 2.0 -1.0 3.0 -1.5 4.0 -2.0 5.0 -2.5 11.0 -5.5 12.0 -6.0 13.0 -6.5 
#[17] 21.0 -10.5 25.0 -12.5 

по запросу.

Как это работает

Предпосылкой является то, что

  • отрицательные числа должны быть умножены на 1/2,
  • положительные числа не должны быть изменены.

Это может быть переведен на

  • если sign(a) == -1 затем умножить a на 1/2
  • если sign(a) == +1 затем умножить a на 1

Теперь, нам нужно найти линейную функцию y = f (x) = p * x + q, который удовлетворяет уравнению uations

  • F (-1) = р + д = 1/2
  • F (1) = р + д = 1.

После решения для р и д мы получаем Р (х) = 1/4 * х + 3/4. С х = знак (a) коэффициент умножить каждый элемент a с является:

1/4 * знак (a) + 3/4

Смежные вопросы