对两个向量应用逻辑计算,然后在第三个向量中返回结果

时间:2019-05-23 21:46:30

标签: r

我对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 个答案:

答案 0 :(得分:1)

?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

答案 1 :(得分:1)

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)

答案 2 :(得分:1)

您的代码中有一些误解:

  1. 在R中,“ NA”被视为字符(字符串在R中称为字符)。正确的 形式为不带引号的NA。
    值得注意的是data.frame会自动将字符转换为可以通过使用data.frame(...,stringsAsFactors = F)禁用的因子类型。
  2. data.frame的每一列都有一个类型,而不是每个元素。因此,当您有一列包含数字和NA的列时,该列的类将是数字,并且is.numeric甚至为NA元素也提供Trueis.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