【问题标题】:Nested loop in R: columns then rowsR中的嵌套循环:列然后行
【发布时间】:2012-02-14 17:16:13
【问题描述】:

我正在尝试在 R 中编写一个嵌套的 for 循环,但遇到了问题。我进行了尽可能多的研究,但找不到(或理解)我需要的帮助。我对 R 相当陌生,因此对于此循环的任何建议将不胜感激,或者如果有更简单、更优雅的方式!

我已经为许多地方(我将它们称为站点)生成了一个每日温度文件,文件列的设置如下:

年月日 unix_time site_a site_b site_c site_d ... on and on

对于每个站点(每列内),我想遍历温度值并创建新列(或新数据框),其数字(生理速率)与这些温度范围相对应。 (例如,低于 6.25 度的温度为 -1.33,6.25 到 8.75 之间的温度为 0.99,等等)。我创建了一个循环,对单列数据执行此操作。例如:

for(i in 1:dim(data)[1]){
if (data$point_a[i]<6.25) data$rate_point_a[i]<--1.33 else
if (data$point_a[i]>=6.25 && data$point_a[i]<8.75) data$rate_point_a[i]<-0.99 else
if (data$point_a[i]>=8.75 && data$point_a[i]<11.25) data$rate_point_a[i]<-3.31 else
if (data$point_a[i]>=11.25 && data$point_a[i]<13.75) data$rate_point_a[i]<-2.56 else
if (data$point_a[i]>=13.75 && data$point_a[i]<16.25) data$rate_point_a[i]<-1.81 else
if (data$point_a[i]>=16.25 && data$point_a[i]<18.75) data$rate_point_a[i]<-2.78 else
if (data$point_a[i]>=18.75 && data$point_a[i]<21.25) data$rate_point_a[i]<-3.75 else
if (data$point_a[i]>=21.25 && data$point_a[i]<23.75) data$rate_point_a[i]<-1.98 else
if (data$point_a[i]>=23.75 && data$point_a[i]<26.25) data$rate_point_a[i]<-0.21
}

上面的代码为我提供了一个名为“rate_site_a”的新列,其中包含我的生理速率。我遇到的麻烦是将这个循环嵌套到另一个贯穿所有列的循环中。我已经尝试过诸如:

for (i in 1:ncol(data)){

#for each row in that column
for (s in 1:length(data)){

    if ([i]<6.25) rate1[s]<--1.33 else  ...

我想我不知道如何让“if else”语句引用正确的位置。我知道我不能将“速率”列添加到现有数据框中,因为这会在我通过循环时增加我的 ncol,所以需要将它们放入另一个数据框(尽管不认为这是我的主要问题)。我将有很多很多点要解决,并且不想一次做一个,因此我尝试嵌套循环。

任何帮助将不胜感激。如果有帮助,这里是一些示例数据的链接。 http://dl.dropbox.com/u/17903768/AVHRR_output.txt提前致谢!

【问题讨论】:

    标签: r for-loop nested-loops


    【解决方案1】:

    使用矢量化的 ifelse:

    ifelse(data$point&lt;= 6.25,-1.33,ifelse(data$point&lt;= 8.25,-0.99,ifelse(data$point&lt;= 11.25,-3.31,.....直到完成。

    例如:

     datap=read.table('http://dl.dropbox.com/u/17903768/AVHRR_output.txt',header=T)
    
    
    apply(datap[,5:9],2,function(x){
    datap$x =   
    ifelse(x<=6.25,1.33,
     ifelse(x<=8.75,-0.99, 
      ifelse(x<=11.25,-3.31, 
       ifelse(x<=13.75,-2.56, 
        ifelse(x<=16.25,-1.81,
         ifelse(x<=18.75,-2.78, 
          ifelse(x<=21.25,-3.75, 
           ifelse(x<=23.75,-1.98,-0.21))))))))})
    

    【讨论】:

    • 非常感谢您的帮助!
    【解决方案2】:

    Andres 的回答非常适合 apply 部分,让您了解所有“温度”列。我被困在这里,没有 R 的副本(在工作中)来试验,但我怀疑你是否创建了一个截止值的向量 xcut &lt;- c(0,6.25,8.75,.11.25,...
    然后就做
    x &lt;- xcut[(which(x&gt;xcut))]
    您将拥有更简单的代码,并且也更易于编辑。 (注意:我添加了0 值以避免小x 值出现问题:-))

    【讨论】:

      【解决方案3】:

      这是另一种仅使用逻辑的方法:

          DAT <- read.table("http://dl.dropbox.com/u/17903768/AVHRR_output.txt",header=TRUE,as.is=TRUE)
      
          recodecolumn <- function(x){
              out <- vector(length=length(x))
              out[x < 6.25] <- 1.33
              out[x >= 6.25 & x < 8.75] <- .99
              out[x >= 8.75 & x < 11.25] <- 3.31
              out[x >= 11.25 & x < 13.25] <- 2.56
              out[x >= 13.25 & x < 16.25] <- 1.81
              out[x >= 16.25 & x < 18.75] <- 2.78
              out[x >= 18.75 & x < 21.25] <- 3.75
              out[x >= 21.25 & x < 23.75] <- 1.98
              out[x >= 23.75 & x < 26.25] <- 0.21
                  out
          }
      
          NewCols <- apply(DAT[,5:9],2,recodecolumn)
          colnames(NewCols) <- paste("rate",1928:1932,sep="_")
          DAT <- cbind(DAT,NewCols)
      

      【讨论】:

      • 谢谢,这很有帮助!我有很多东西要学!
      【解决方案4】:

      我发现findInterval 在这种情况下很有用,而不是嵌套的 if else 语句,因为它已经向量化并返回截止点向量中的位置。

       DAT <- read.table("http://dl.dropbox.com/u/17903768/AVHRR_output.txt",header=TRUE,as.is=TRUE)
      
       recode.fn <- function(x){
          cut.vec <- c(0, seq(6.25,26.25,by = 2.5),Inf)
          recode.val <- c(-1.33, 0.99, 3.31, 2.56,1.81,2.78,3.75,1.98, 0.21)
          cut.interval <- findInterval(x, cut.vec, FALSE)
          return(recode.val[cut.interval])
       }
      
      # Add on recoded data to existing data frame
      DAT[,10:14] <- sapply(DAT[,5:9],FUN=recode.fn)
      

      【讨论】:

      • 该死!忍者让我领先一分钟 :-) 。假设我做对了,我的答案只是 findInterval 的一个变体。很好的答案,吉姆。
      • 以前没见过这个,不错
      猜你喜欢
      • 1970-01-01
      • 2015-07-01
      • 2022-10-14
      • 1970-01-01
      • 1970-01-01
      • 2021-03-11
      • 1970-01-01
      • 1970-01-01
      • 2020-10-06
      相关资源
      最近更新 更多