简体   繁体   English

R中的嵌套循环:列然后行

[英]Nested loop in R: columns then rows

I am trying to write a nested for loop in R, but am running into problems. 我正在尝试在R中编写一个嵌套的for循环,但遇到了问题。 I have researched as much as possible but can't find (or understand) the help I need. 我已进行了尽可能多的研究,但找不到(或理解)我需要的帮助。 I am fairly new to R, so any advice on this looping would be appreciated, or if there is a simpler, more elegant way! 我对R还是很陌生,因此,如果对这种循环有任何建议,或者如果有一种更简单,更优雅的方法,将不胜感激!

I have generated a file of daily temperatures for many many locations (I'll call them sites), and the file columns are set up like this: 我已经为许多位置(我称它们为站点)生成了每日温度文件,文件列的设置如下:

year month day unix_time site_a site_b site_c site_d ... on and on 年月日unix_time site_a site_b site_c site_d ...等

For each site (within each column), I want to run through the temperature values and create new columns (or a new data frame) with a number (a physiological rate) that corresponds with a range of those temperatures. 对于每个站点(在每列内),我要遍历温度值并创建一个新列(或新数据框),并使用与这些温度范围相对应的数字(生理速率)。 (for example, temperatures less than 6.25 degrees have a rate of -1.33, temperatures between 6.25 and 8.75 have a rate of 0.99, etc). (例如,低于6.25度的温度具有-1.33的速率,在6.25至8.75之间的温度具有0.99的速率,等等)。 I have created a loop that does this for a single column of data. 我创建了一个循环,对单个数据列执行此操作。 For example: 例如:

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
}

The above code gives me a new column called "rate_site_a" that has my physiological rates. 上面的代码给了我一个名为“ rate_site_a”的新列,该列具有我的生理速率。 What I am having trouble doing is nesting this loop into another loop that runs through all of the columns. 我遇到的麻烦是将这个循环嵌套到贯穿所有列的另一个循环中。 I have tried things such as: 我已经尝试过诸如:

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  ...

I guess I don't know how to make the "if else" statement refer to the correct places. 我想我不知道如何使“ if else”语句引用正确的位置。 I know that I can't add the "rate" columns onto the existing data frame, as this would increase my ncol as I go through the loop, so need to put them into another data frame (though don't think this is my main issue). 我知道我无法将“ rate”列添加到现有数据框中,因为这会增加我在循环中的ncol,因此需要将它们放入另一个数据框中(尽管不要认为这是我的主要问题)。 I am going to have many many many points to work through and would rather not have to do them one at a time, hence my attempt at a nested loop. 我将要处理很多很多点,而不希望一次只做一次,因此我尝试嵌套循环。

Any help would be much appreciated. 任何帮助将非常感激。 Here is a link to some sample data if that is helpful. 如果有帮助,这里是一些示例数据的链接。 http://dl.dropbox.com/u/17903768/AVHRR_output.txt Thanks in advance! http://dl.dropbox.com/u/17903768/AVHRR_output.txt预先感谢!

Use ifelse which is vectorized: 使用向量化的ifelse:

ifelse(data$point<= 6.25,-1.33,ifelse(data$point<= 8.25,-0.99,ifelse(data$point<= 11.25,-3.31,.... .Until finished. ifelse(data$point<= 6.25,-1.33,ifelse(data$point<= 8.25,-0.99,ifelse(data$point<= 11.25,-3.31,....

For instance: 例如:

 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))))))))})

Andres answer is great for the apply part to get you thru all the "temperature" columns. 安德列斯(Andres)的答案对于apply部分非常有用,它可以使您遍及所有“温度”列。 I'm stuck here without a copy of R (at work) to experiment with, but I suspect if you create a vector of your cutoff values xcut <- c(0,6.25,8.75,.11.25,... 我被困在这里,没有R的副本(正在工作)进行实验,但是我怀疑您是否创建了一个截止值的向量xcut <- c(0,6.25,8.75,.11.25,...
and just do 然后做
x <- xcut[(which(x>xcut))]
you'll have a much simpler bit of code, and easier to edit as well. 您将拥有更简单的代码,并且也更容易编辑。 (note: I added the 0 value to avoid problems with small x values :-) ) (注意:我添加了0值以避免x值小的问题:-))

here's another way using just logicals: 这是仅使用逻辑的另一种方法:

    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)

I find that findInterval is useful in situations like this instead of nested if else statements as it is already vectorized and returns the position within a vector of cutoff points. 我发现在这样的情况下, findInterval很有用,而不是嵌套if语句,因为它已经向量化并返回截止点向量内的位置。

 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM