2012-06-21 28 views
0

我有一个函数(bobB)似乎陷入了一个while循环。当我打逃脱,并在警告一下()我收到以下错误:min()R函数中的while循环出错-a调试挑战R爱好者

Warning message: 
In min(xf, yf) : no non-missing arguments to min; returning Inf 

一些示例代码:

#I have the data: 

x<-"A03" 
y<-"A24" 

sitex<-c("Sp1","Sp1","Sp3","Sp3") 
sitey<-c("Sp2","Sp4","Sp2","Sp4") 
gsim<-c(0.2,0.3,0.4,0.1) 
gsim<-data.frame(sitex,sitey,gsim) 

site<-c("A03","A03","A03","A03","A24","A24","A24","A24") 
species<-c("Sp1","Sp1","Sp3","Sp4","Sp1","Sp1","Sp3","Sp4") 
freq<-c(0.2,0.3,0.4,0.1,0.3,0.3,0,0.4) 
ssf<-data.frame(site,species,freq,stringsAsFactors=FALSE) 

#My function: 

bobB <- function (x, y, ssf, gsim) { 

#*Step 1.* Create an empty matrix 'specfreq' to fill 

#Selects the species frequency data greater than 0 for the two sites being compared 

ssfx <- ssf[ssf$site == x & ssf$freq >0,] 
ssfy <- ssf[ssf$site == y & ssf$freq >0,] 

#pull out the species that are present at site x and/or site y using a merge, 
#this is needed to create the initial empty matrix 

m<-(merge(ssfx,ssfy,all=TRUE)) 
species<-unique(m$species) 

#Creates an empty matrix of the frequency of each species at site x and y 

specfreq <- matrix(0, length(species), 2, dimnames=list(species,c(x,y))) 

#*Step 2.* Fill empty matrix 'specfreq' with data from data.frame 'ssf' 

for(i in 1:nrow(ssf{specfreq[rownames(specfreq)==ssf[i,"species"],colnames(specfreq)==ssf[i,"site"]] <- ssf[i,"freq"]} 

#*Step 3.* For species present at site x and y remove the minimum of the two from both 
#find minimum frequency for each species for site x and y 

a <- pmin(specfreq[,x], specfreq[,y]) 

#subtract 'a' from current 'specfreq' 

specfreq <- specfreq - a 

#*Step 4.* Calulate variable B 

#Set answer to 0 

answer <- 0 

#while 'specfreq' contains data (i.e. is >0) keep doing the following 

while(sum(specfreq) > 1e-10) { 

#Find species remaining at site x 

sx <- species[specfreq[,1] > 0] 

#Find species remaining at site y 

sy <- species[specfreq[,2] > 0]  

#Pull out the gsim value for sx and sy 

gsimre <-gsim[gsim$sitex %in% sx & gsim$sitey %in% sy,] 

#determines the row containing the maximum value for remaining gsim and assigns it to i  

i <- which.max(gsimre$gsim) 

#once the max gsim value has been found (i) we go back to the specfreq matrix and filter 
#out the frequency of the site x species associated with i 

xf <- specfreq[(gsimre$sitex[i]),x] 

#and the frequency of the site y species associated with i 

yf <- specfreq[(gsimre$sitey[i]),y] 

#The frequency of the species at site x associated with the greatest i is multiplied by i   

answer <- answer + xf * gsimre$gsim[i] 

#Then take the minimum common frequency for the two species associated with i 

f <- min(xf,yf) 

#Subtract theminimum common frequency from both the site x and site y column 

specfreq[gsimre$sitex[i],x] <- specfreq[gsimre$sitex[i],x]-f 
specfreq[gsimre$sitey[i],y] <- specfreq[gsimre$sitey[i],y]-f 
} 
answer 
} 
bobB(x, y, ssf, gsim) 
+0

调试建议:http://stackoverflow.com/questions/1882734/what-is-your-favorite-r-debugging-trick/5156351#5156351 –

+2

我*如果让我更容易将代码复制并粘贴到干净的会话中,可能会查看此内容。因此,对于初学者来说,将您的评论改为嵌入代码评论,或将其删除(即给我一个单独的代码块)。 – Andrie

+2

为什么你忽略了你之前发布的这个问题的评论和回答?很显然'xf'和'yf'是空的,所以你需要学习调试。向后查看'x,y,gsimre $ sitex [i]'等的值,直到找到你的错误。 –

回答

0

好了,所以这里是你的问题(我认为):

xf <- specfreq[(gsimre$sitex[i]),x] 
yf <- specfreq[(gsimre$sitey[i]),y] 

(gsimre$sitex[i])(gsimre$sitey[i])是这些因素,这意味着当您使用它们来索引某些内容时,会将其解释为数字而不是字符。 的确:

gsimre$sitey 
[1] Sp4 
Levels: Sp2 Sp4 

SP4中,是所述第二因子,具有为2的数值,因此是specfreq[(gsimre$sitey[i]),y]其中specfreq[2,2]为0

因此,这应该做的伎俩:

xf <- specfreq[as.character(gsimre$sitex[i]),x] 
yf <- specfreq[as.character(gsimre$sitey[i]),y] 

或者您声明它们是开头的字符串而不是因子,如您对ssf所做的那样,但不是gsim

gsim<-data.frame(sitex,sitey,gsim, stringsAsFactors=FALSE) 

由于这个错误yf等于0因此f=min(xf,yf)总是等于0,因此您的无限循环。

P. S.:answer应该在while循环之外,如果你想让函数返回它,即

} 
answer 
} 

代替

answer 
    } 
} 
+0

谢谢plannapus。这似乎工作,我现在可以好玩BobB。然而,当我运行组合函数bobA,bobB和bobC的'external function'时,我仍然得到错误“In min(xf,yf):没有非缺少的参数到min;返回Inf”。尽管如此,我会将其作为一个不同的问题发布再次感谢! – Elizabeth