#r #if-statement #na
#r #if-оператор #na
Вопрос:
У меня есть функция, которая вычисляет разницу между строками (на основе одних и тех же столбцов) в 2 наборах данных. Вот пример и функция
#################
## Sample ##
#################
# data frame for recipients
IDr= c(seq(1,4))
Blood_type_r=c("A","B","AB","O")
data_R=data.frame(IDr,Blood_type_r,A=rep(0,4),B=c(rep(0,3),1),C=c(rep(1,3),0),D=rep(1,4),E=c(rep(0,2),rep(1,1),0),stringsAsFactors=FALSE)
data_R
IDr Blood_type_r A B C D E
1 1 A 0 0 1 1 0
2 2 B 0 0 1 1 0
3 3 AB 0 0 1 1 1
4 4 O 0 1 0 1 0
# data frame for donors
IDd= c(seq(1,8))
Blood_type_d= c(rep("A", each=2),rep("B", each=2),rep("AB", each=2),rep("O", each=2))
WD= c(rep(0.25, each=2),rep(0.125, each=2),rep(0.125, each=2),rep(0.5, each=2))
data_D=data.frame(IDd,Blood_type_d,A=c(rep(0,6),1,1),B=c(rep(0,6),1,1),C=c(rep(1,7),0),D=rep(1,8),E=c(rep(0,6),rep(1,1),0),WD,stringsAsFactors=FALSE)
data_D
IDd Blood_type_d A B C D E WD
1 1 A 0 0 1 1 0 0.250
2 2 A 0 0 1 1 0 0.250
3 3 B 0 0 1 1 0 0.125
4 4 B 0 0 1 1 0 0.125
5 5 AB 0 0 1 1 0 0.125
6 6 AB 0 0 1 1 0 0.125
7 7 O 1 1 1 1 1 0.500
8 8 O 1 1 0 1 0 0.500
# function
soustraction.i=function(D,R,i,threshold){
D=as.data.frame(D)
R=as.data.frame(R)
dif=map2_df(D, R[i,], `-`)
dif[dif<0] = 0
dif$mismatch=rowSums(dif)
dif=dif[which(dif$mismatch <= threshold),]
return(dif)
}
soustraction.i(data_D[,3:7],data_R[,3:7],1,3)
# A tibble: 8 x 6
A B C D E mismatch
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 0 0 0 0 0 0
2 0 0 0 0 0 0
3 0 0 0 0 0 0
4 0 0 0 0 0 0
5 0 0 0 0 0 0
6 0 0 0 0 0 0
7 1 1 0 0 1 3
8 1 1 0 0 0 2
Что я хочу сделать, так это когда я устанавливаю свой порог 0
равным, а мой mismatch
больше 0
, я не хочу терять этих пациентов, вместо этого я хочу сохранить их и присвоить NA
значение, например, если я установлю порог 0
равным, я получу
soustraction.i(data_D[,3:7],data_R[,3:7],1,0)
# A tibble: 6 x 6
A B C D E mismatch
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 0 0 0 0 0 0
2 0 0 0 0 0 0
3 0 0 0 0 0 0
4 0 0 0 0 0 0
5 0 0 0 0 0 0
6 0 0 0 0 0 0
Я теряю 2 пациента, которым я хотел бы присвоить NA
значение. Таким образом, результат будет следующим
# Desired output
# A tibble: 8 x 6
A B C D E mismatch
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 0 0 0 0 0 0
2 0 0 0 0 0 0
3 0 0 0 0 0 0
4 0 0 0 0 0 0
5 0 0 0 0 0 0
6 0 0 0 0 0 0
7 1 1 0 0 1 NA
8 1 1 0 0 0 NA
Вот то, что я пробовал до сих пор, и это дает мне предупреждение и не делает правильные вещи
soustraction.j=function(D,R,i,threshold){
D=as.data.frame(D)
R=as.data.frame(R)
dif=map2_df(D, R[i,], `-`)
dif[dif<0] = 0
dif$mismatch=rowSums(dif)
if(threshold==0){
if(dif$mismatch > 0){
dif$mismatch= NA
}
}else{
dif=dif[which(dif$mismatch <= threshold),]
}
return(dif)
}
soustraction.j(data_D[,3:7],data_R[,3:7],1,0)
# A tibble: 8 x 6
A B C D E mismatch
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 0 0 0 0 0 0
2 0 0 0 0 0 0
3 0 0 0 0 0 0
4 0 0 0 0 0 0
5 0 0 0 0 0 0
6 0 0 0 0 0 0
7 1 1 0 0 1 3
8 1 1 0 0 0 2
#Warning message:
#In if (dif$mismatch > 0) { :
# the condition has length > 1 and only the first element will be used
Заранее благодарим вас за помощь
Ответ №1:
Вот такое dplyr
решение. Он должен работать для when threshold == 0
и обобщаться на другие пороговые значения:
soustraction.i=function(D,R,i,threshold){
D=as.data.frame(D)
R=as.data.frame(R)
dif=map2_df(D, R[i,], `-`)
dif[dif<0] = 0
dif$mismatch=rowSums(dif)
dif <- dif %>%
mutate(mismatch = case_when(mismatch > threshold ~ NA_real_,
TRUE ~ mismatch))
return(dif)
}
Выходной сигнал:
soustraction.i(data_D[,3:7],data_R[,3:7],1,0)
# A tibble: 8 x 6
A B C D E mismatch
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 0 0 0 0 0 0
2 0 0 0 0 0 0
3 0 0 0 0 0 0
4 0 0 0 0 0 0
5 0 0 0 0 0 0
6 0 0 0 0 0 0
7 1 1 0 0 1 NA
8 1 1 0 0 0 NA
Редактировать
Вот один из примеров « dplyr
переработанной» версии вашей функции
soustraction.i <- function(D,R,i,threshold){
D <- as_tibble(D)
R <- as_tibble(R)
dif <- map2_df(D, R[i,], `-`) %>%
mutate(across(everything(), ~ifelse(.x < 0, 0, .x))) %>%
rowwise() %>%
mutate(mismatch = sum(c_across(everything())),
mismatch = case_when(as.numeric(mismatch) > threshold ~ NA_real_,
TRUE ~ mismatch))
return(dif)
}
Комментарии:
1. Спасибо @latlio за ваш ответ! Это то, что я искал. Я ценю это.
Ответ №2:
Вместо того, чтобы брать подмножество строк, вы можете присвоить им значение NA
where mismatch
больше, чем threshold
.
soustraction.i=function(D,R,i,threshold){
D=as.data.frame(D)
R=as.data.frame(R)
dif= purrr::map2_df(D, R[i,], `-`)
dif[dif<0] = 0
dif$mismatch=rowSums(dif)
dif$mismatch[dif$mismatch > threshold] <- NA
return(dif)
}
Вы можете проверить вывод :
soustraction.i(data_D[,3:7],data_R[,3:7],1,3)
# A tibble: 8 x 6
# A B C D E mismatch
# <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1 0 0 0 0 0 0
#2 0 0 0 0 0 0
#3 0 0 0 0 0 0
#4 0 0 0 0 0 0
#5 0 0 0 0 0 0
#6 0 0 0 0 0 0
#7 1 1 0 0 1 3
#8 1 1 0 0 0 2
soustraction.i(data_D[,3:7],data_R[,3:7],1,0)
# A tibble: 8 x 6
# A B C D E mismatch
# <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1 0 0 0 0 0 0
#2 0 0 0 0 0 0
#3 0 0 0 0 0 0
#4 0 0 0 0 0 0
#5 0 0 0 0 0 0
#6 0 0 0 0 0 0
#7 1 1 0 0 1 NA
#8 1 1 0 0 0 NA