微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

无论我是否输出ggplot图,函数的结果都不同,为什么?

如何解决无论我是否输出ggplot图,函数的结果都不同,为什么?

TLDR:函数是否根据绘制结果输出不同的结果。

基本上,我有一个函数,可以基于模型(beta0; beta1)中的某些系数来计算一些点。该函数可以通过showPlot = TRUE输出图形,也可以不通过showPlot = FALSE输出图形。

次级功能中使用了初始功能,这里是:

library(tidyverse)

defun <- function(dm,b = c(beta0,beta1)){
  p <- 1 / (1 + exp(-(b[1] + b[2]*dm)))
  return(p)
}

beta0 <- 3.831 
beta1 <- -0.02253

现在来了怪异的部分,这是辅助功能

fun1<- function (vel = 1,delays = c(50,400),durbur = 5,distrec = 1000,dist = 2000,defun,outerLim = c(0,0),simuln = 1000,showPlot = FALSE) 
{
  if (any(!is.function(defun))) 
    stop("Error: argument 'defun' must be a function...")
  if (any(is.na(distrec))) 
    distrec <- 0
  xLim <- c(0,sum(distrec) + sum(outerLim))
  recLoc <- c(outerLim[1],outerLim[1] + cumsum(distrec))
  yLim <- c(-dist,dist)
  transect <- floor((diff(yLim)/vel)/delays[1])
  del <- matrix(runif(transect * simuln,delays[1],delays[2]),nrow = simuln,ncol = transect)
  del <- del + durbur
  trans <- t(apply(del,1,cumsum))
  trans <- trans - matrix(runif(simuln,trans[,transect/2],(transect/2) + 1]),ncol    = transect)
  an.x <- matrix(runif(simuln,xLim[1],xLim[2]),ncol = transect)
  an.y <- matrix(trans * vel,ncol = transect)
  if (showPlot){
    
    # converting x coordinates to datframe
    xcor = pivot_longer(data = data.frame(an.x),everything()) %>%
      mutate(fish = as.numeric(sort(rep(sample(1:simuln),each = transect)))) %>% select(-name) %>% 
      rename(x = value,fish = fish)
    
    # converting y coordinates to dataframe
    ycor = pivot_longer(data = data.frame(an.y),everything()) %>% select(-name) %>% 
      rename(y = value)
    
    # binding x and y coordinates
    df3 = cbind(xcor,ycor)
    
    # mutate to factor for graphing purposes
    df3 = df3[,c("x","y","fish")] %>% mutate_at(vars(fish),~ as.factor(.))
    
    print(ggplot() + xlim(0,xLim[2]) + 
            ylim(-dist,dist) + 
            geom_point(aes(x = recLoc,y = rep(0,length(recLoc))),colour = "red",size = 4) + 
            labs(x = "Horizontal spread",y = "Vertical spread") + 
            geom_line(aes(x = x,y = y),data = df3) + 
            geom_point(aes(x = x,y = y,colour = fish),data = df3))
  }
  for (i in 1:length(recLoc)) {
    if (i == 1) {
      succ <- detP <- distM <- vector("list",length(recLoc))
      nDets <- matrix(NA,ncol = length(recLoc))
    }
    distM[[i]] <- sqrt((an.x - recLoc[i])^2 + (an.y)^2)
    detP[[i]] <- matrix(defun(distM[[i]]),nrow = simuln)
    succ[[i]] <- matrix(rbinom(length(detP[[i]]),detP[[i]]),nrow = simuln)
    nDets[,i] <- rowSums(succ[[i]])
  }
  maxndet <- apply(nDets,max)
  probsdet <- mean(maxndet > 1)
  return(data.frame(probsdet = probsdet))
}

set.seed(12331)

# with showPlot = FALSE
fun1(defun = defun,vel = 1,simuln = 20,durbur = 5.0,distrec = rep(1000,10),dist = 1000,outerLim =   c(500,500),showPlot = FALSE)

# with showPlot = TRUE
fun1(defun = defun,showPlot = TRUE)

除了我在运行showPlot = TRUE时得到的结果(即返回的probsdet有所不同)和不查询图的事实之外,其他所有方法似乎都可以正常工作。我不确定这是什么原因,是否与ggplot相关的问题/ tidyverse或错误的编码。

有人可以解释原因以及如何纠正这种行为吗?

解决方法

您的函数具有随机性,因此除非您使用set.seed,否则您不应期望两次连续运行的结果都相同。 请注意,每次运行该功能时都需要重置种子。

fun1(defun = defun)
#   probsdet
# 1    0.147

fun1(defun = defun)
#   probsdet
# 1    0.156


set.seed(47)
fun1(defun = defun)
#   probsdet
# 1    0.155
set.seed(47)
fun1(defun = defun)
#   probsdet
# 1    0.155

if(showPlot){}子句中的代码也使用随机性(通过sample()函数),因此会影响随机数生成器的状态。我们可以将绘图代码移到函数的末尾,这样无论是否有绘图,所有非绘图计算都将首先完成。

fun1<- function (vel = 1,delays = c(50,400),durbur = 5,distrec = 1000,dist = 2000,defun,outerLim = c(0,0),simuln = 1000,showPlot = FALSE) 
{
  if (any(!is.function(defun))) 
    stop("Error: argument 'defun' must be a function...")
  if (any(is.na(distrec))) 
    distrec <- 0
  xLim <- c(0,sum(distrec) + sum(outerLim))
  recLoc <- c(outerLim[1],outerLim[1] + cumsum(distrec))
  yLim <- c(-dist,dist)
  transect <- floor((diff(yLim)/vel)/delays[1])
  del <- matrix(runif(transect * simuln,delays[1],delays[2]),nrow = simuln,ncol = transect)
  del <- del + durbur
  trans <- t(apply(del,1,cumsum))
  trans <- trans - matrix(runif(simuln,trans[,transect/2],(transect/2) + 1]),ncol    = transect)
  an.x <- matrix(runif(simuln,xLim[1],xLim[2]),ncol = transect)
  an.y <- matrix(trans * vel,ncol = transect)

  for (i in 1:length(recLoc)) {
    if (i == 1) {
      succ <- detP <- distM <- vector("list",length(recLoc))
      nDets <- matrix(NA,ncol = length(recLoc))
    }
    distM[[i]] <- sqrt((an.x - recLoc[i])^2 + (an.y)^2)
    detP[[i]] <- matrix(defun(distM[[i]]),nrow = simuln)
    succ[[i]] <- matrix(rbinom(length(detP[[i]]),detP[[i]]),nrow = simuln)
    nDets[,i] <- rowSums(succ[[i]])
  }
  maxndet <- apply(nDets,max)
  probsdet <- mean(maxndet > 1)
  
  if (showPlot){
    
    # converting x coordinates to datframe
    xcor = pivot_longer(data = data.frame(an.x),everything()) %>%
      mutate(fish = as.numeric(sort(rep(sample(1:simuln),each = transect)))) %>% select(-name) %>% 
      rename(x = value,fish = fish)
    
    # converting y coordinates to dataframe
    ycor = pivot_longer(data = data.frame(an.y),everything()) %>% select(-name) %>% 
      rename(y = value)
    
    # binding x and y coordinates
    df3 = cbind(xcor,ycor)
    
    # mutate to factor for graphing purposes
    df3 = df3[,c("x","y","fish")] %>% mutate_at(vars(fish),~ as.factor(.))
    
    print(ggplot() + xlim(0,xLim[2]) + 
            ylim(-dist,dist) + 
            geom_point(aes(x = recLoc,y = rep(0,length(recLoc))),colour = "red",size = 4) + 
            labs(x = "Horizontal spread",y = "Vertical spread") + 
            geom_line(aes(x = x,y = y),data = df3) + 
            geom_point(aes(x = x,y = y,colour = fish),data = df3))
  }
  
  return(data.frame(probsdet = probsdet))
}

然后,使用该功能的该版本,我们可以重现结果:

set.seed(47)
fun1(defun = defun,showPlot = TRUE)
#   probsdet
# 1    0.155

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。