Применение логического вычисления к двум векторам и возвращение результата в третьем векторе - PullRequest
0 голосов
/ 24 мая 2019

Я довольно новичок в R и у меня проблемы с реализацией чего-то, что должно быть очень простым.Может ли кто-нибудь указать мне правильное направление?

Мне нужно применить логическое вычисление, основанное на значениях двух векторов, и вернуть значение этой функции в третьем векторе.

Я хочу сделать это в пользовательской функции, чтобы я мог легко применить ее в нескольких других областях алгоритма и с легкостью вносить изменения в реализацию.

Вот что я попробовал,но я не могу заставить эту реализацию работать.Я полагаю, что это потому, что я не могу отправить векторы в качестве параметров этой функции.

<!-- language: python -->
calcSignal <- function(fVector, sVector) {
  if(!is.numeric(fVector) || !is.numeric(sVector)) {
    0
  }
  else if (fVector > sVector) {
    1
  }
  else if (fVector < sVector) {
    -1
  }
  else {
    0  # is equal case        
  }
}

# set up data frame
df <- data.frame(x=c("NA", 2, 9, 7, 0, 5), y=c(4, 1, 5, 9, 0, "NA"))
# call function
df$z <- calcSignal(df$x, df$y)

Я хочу, чтобы вывод был вектором со следующими значениями, но я не реализую функцию правильно.

[0, -1,1, -1,0,0]

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

Я ценю вашу помощь!

Ответы [ 3 ]

1 голос
/ 24 мая 2019

ifelse - еще одна удобная функция.Менее элегантно, чем sign хотя

df <- data.frame(x=c(NA, 2, 9, 7, 0, 5), y=c(4, 1, 5, 9, 0, NA))

cs <- function(x, y){
  a <- x > y
  b <- x < y

  out <- ifelse(a, 1, ifelse(b, -1, 0))

  ifelse(is.na(out), 0, out)

}
cs(df$x, df$y)

1 голос
/ 24 мая 2019

В вашем коде есть некоторые недоразумения:

  1. в R "NA" считается символом (строка называется символом в R). правильный Форма - это без кавычек.
    Стоит отметить, что data.frame автоматически преобразует символ в тип фактора, который можно отключить с помощью data.frame(...,stringsAsFactors = F).
  2. каждый столбец data.frame имеет тип, а не каждый элемент. поэтому, когда у вас есть столбец, содержащий числа и NA, класс этого столбца будет числовым, и is.numeric даст вам True даже для элементов NA. is.na сделает работу
  3. || сравнивает только первый элемент каждого вектора. | выполняет поэлементное сравнение.

Теперь давайте реализуем то, что вы хотели:

Реализация 1 :

#set up data frame
df <- data.frame(x=c(NA, 2, 9, 7, 0, 5), y=c(4, 1, 5, 9, 0, NA))

calcSignal <- function(f,s){
  if(is.na(f) | is.na(s))
    return(0)
  else if(f>s)
    return(1)
  else if(f<s)
    return(-1)
  else
    return(0)
}
df$z = mapply(calcSignal, df$x, df$y, SIMPLIFY = T)

для поэтапного запуска функции на двух или более векторах мы можем использовать mapply.

Реализация 2
не сильно отличается от предыдущего. здесь эта функция проще в использовании.

#set up data frame
df <- data.frame(x=c(NA, 2, 9, 7, 0, 5), y=c(4, 1, 5, 9, 0, NA))

calcSignal <- function(fVector, sVector) {
  res = mapply(function(f,s){
    if(is.na(f) | is.na(s))
      return(0)
    else if(f>s)
      return(1)
    else if(f<s)
      return(-1)
    else
      return(0)
  },fVector,sVector,SIMPLIFY = T)
  return(res)
}
df$z = calcSignal(df$x,df$y)

Реализация 3 (векторизация)
Этот намного лучше. потому что это векторизация и намного быстрее:

calcSignal <- function(fVector, sVector) {
  res = rep(0,length(fVector))
  res[fVector>sVector] = 1
  res[fVector<sVector] = -1

  #This line isn't necessary.It's just for clarification
  res[(is.na(fVector) | is.na(sVector))] = 0

  return(res)
}
df$z = calcSignal(df$x,df$y)

Выход:

> df
   x  y  z
1 NA  4  0
2  2  1  1
3  9  5  1
4  7  9 -1
5  0  0  0
6  5 NA  0
1 голос
/ 24 мая 2019

Лупаж не нужен, поскольку ?sign имеет вашу спину:

# fixing the "NA" issue:
df <- data.frame(x=c(NA, 2, 9, 7, 0, 5), y=c(4, 1, 5, 9, 0, NA))

s <- sign(df$x - df$y)
s[is.na(s)] <- 0
s
#[1]  0  1  1 -1  0  0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...