r – 嵌套循环中的索引

我是R和这个网站的新手.我的目标是以下,确实是不必要的神秘代码是创建一个R函数,在ggplot2中生成一种特殊类型的盒子图.我首先需要通过计算我稍后希望绘制的变量来处理其中的潜在输入.

我首先生成一些称为数据的随机数据:

c1=rnorm(98,47,23)
c2=rnorm(98,56,13)
c3=rnorm(98,52,7)
fila1=as.matrix(t(c(-2,15,30)))
colnames(fila1)=c("c1","c2","c3")
fila2=as.matrix(t(c(-20,5,20)))
colnames(fila2)=c("c1","c2","c3")
datos=rbind(data.frame(c1,c2,c3),fila1,fila2)
rm(c1,c2,c3,fila1,fila2)

然后,我计算变量以便稍后绘制,其中包括数据中每个当前列的平均值(puntoMedio),第一和第三四分位数(cuar1,cuar3),内四分位数范围(iqr),下限潜在的submean whiskers(limInf),潜在的supermean whiskers(limSup)和异常值的上限(submean outliers vAtInf和supermean outliers vAtSup将在vAt中组合):

puntoMedio=apply(datos,MARGIN=2,FUN=mean)
cuar1=apply(datos,MARGIN=2,FUN=quantile,probs=.25)
cuar3=apply(datos,MARGIN=2,FUN=quantile,probs=.75)
cuar=rbind(cuar1,cuar3)
iqr=apply(cuar,MARGIN=2,FUN=diff)
cuar=rbind(cuar,iqr,puntoMedio)
limInf=array(dim=ncol(datos))
  for(i in 1:ncol(datos)){
    limInf0=as.matrix(t(cuar[1,]-1.5*cuar[3,]))
    if(length(datos[datos[,i]<limInf0[,i],i])>0){
      limInf[i]=limInf0[,i]
    }else{limInf[i]=min(datos[,i])}
  }
limSup=array(dim=ncol(datos))
  for(i in 1:ncol(datos)){
    limSup0=as.matrix(t(cuar[2,]+1.5*cuar[3,]))
    if(length(datos[datos[,i]>limSup0[,i],i])>0){
      limSup[i]=limSup0[,i]
    }else{limSup[i]=max(datos[,i])}
  }
d=data.frame(t(rbind(cuar,limInf,limSup)))
rm(cuar)
vAtInf=datos
  for(i in 1:ncol(vAtInf)){
    vAtInf[vAtInf[,i]>limInf0[,i],i]=NA
  }
  colnames(vAtInf)=c("vAtInfc1","vAtInfc2","vAtInfc3")
vAtSup=datos
  for(i in 1:ncol(vAtSup)){
    vAtSup[vAtSup[,i]<limSup0[,i],i]=NA
  }
  colnames(vAtSup)=c("vAtSupc1","vAtSupc2","vAtSupc3")
datos=cbind(datos,vAtInf,vAtSup)
rm(limInf0,limSup0,cuar1,cuar3,i,iqr,limInf,limSup,puntoMedio)

在此之前,一切都按预期工作.我有两个数据框d和数据,前者在这里没有兴趣,后者在这个特定情况下包括九列:所有值中的三个,相应的子范围异常值中的三个和相应的超级异常值中的三个(后者六个填充NA).我现在希望按列提取所有异常值,因此我尝试制定以下循环.虽然它既不会产生错误也不会发出警告,但它也不能在vAt中提供所需的输出(同样,数据中的列[列4:9]异常值).然后,就我能够辨别而言,问题出现在嵌套的for循环中,在尝试将i输入到vAt时:循环的每次迭代都会擦除最后一次,这样在完成整个循环时,vAt仅包含NA和最后一列/最后一次迭代中的异常值.

for(i in ((ncol(datos)/3)+1):ncol(datos)){
    vAt=matrix(nrow=.25*nrow(datos),ncol=ncol(datos)-(ncol(datos)/3))
    colnames(vAt)=c(((ncol(datos)/3)+1):ncol(datos))
    if(length(datos[,i][is.na(datos[,i])==F])>0){
        for(j in 1:(length(datos[,i][is.na(datos[,i])==F]))){
            nom=as.character(i)
            vAt[j,nom]=datos[,i][is.na(datos[,i])==F][j]
        }
    }else{next}
}

我找不到任何能回答我问题的existent thread了.谢谢你的帮助.

最佳答案 问题是你在这里初始化循环中的vAt.

在for循环之外移动初始化语句将解决您面临的问题:

vAt=matrix(nrow=.25*nrow(datos),ncol=ncol(datos)-(ncol(datos)/3))
colnames(vAt)=c(((ncol(datos)/3)+1):ncol(datos))
for(i in ((ncol(datos)/3)+1):ncol(datos)){
    if(length(datos[,i][is.na(datos[,i])==F])>0){
        for(j in 1:(length(datos[,i][is.na(datos[,i])==F]))){
            nom=as.character(i)
            vAt[j,nom]=datos[,i][is.na(datos[,i])==F][j]
        }
    }else{next}
}

但是,您可以对代码进行各种改进:

>使用矢量化和* ply函数代替for循环.
>不将逻辑向量与== F进行比较,而只使用!is.na(…).
>使用sum(is.na(…))代替长度(d [,i] [!is.na(…)])

还有一些.这些不会改变代码的正确性,但会使其更有效,更具惯用性.

点赞