В вашем коде есть некоторые недоразумения:
- в R "NA" считается символом (строка называется символом в R). правильный
Форма - это без кавычек.
Стоит отметить, что data.frame автоматически преобразует символ в тип фактора, который можно отключить с помощью data.frame(...,stringsAsFactors = F)
.
- каждый столбец data.frame имеет тип, а не каждый элемент. поэтому, когда у вас есть столбец, содержащий числа и NA, класс этого столбца будет числовым, и
is.numeric
даст вам True
даже для элементов NA. is.na
сделает работу
||
сравнивает только первый элемент каждого вектора. |
выполняет поэлементное сравнение.
Теперь давайте реализуем то, что вы хотели:
Реализация 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