我正在尝试在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”语句引用正确的地方。我知道我不能将“rate”列添加到现有数据框中,因为这会增加我的ncol,因为我需要将它们放入另一个数据框中(尽管不要认为这是我的主要问题)。我将要完成很多很多要点,而不是一次只做一个,因此我尝试了一个嵌套循环。
非常感谢任何帮助。如果有帮助,这里是一些示例数据的链接。 http://dl.dropbox.com/u/17903768/AVHRR_output.txt提前致谢!
答案 0 :(得分:1)
使用矢量化的ifelse:
ifelse(data$point<= 6.25,-1.33,ifelse(data$point<= 8.25,-0.99,ifelse(data$point<= 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))))))))})
答案 1 :(得分:1)
Andres的答案非常适合apply
部分,让您通过所有“温度”列。我被困在这里没有R(在工作中)的副本进行试验,但我怀疑你是否创建了一个截止值的向量
xcut <- c(0,6.25,8.75,.11.25,...
而且只是做
x <- xcut[(which(x>xcut))]
你将拥有更简单的代码,也更容易编辑。 (注意:我添加了0
值以避免小x
值出现问题:-))
答案 2 :(得分:0)
这是使用逻辑的另一种方式:
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)
答案 3 :(得分:0)
我发现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)