[英]Nested loop in R: columns then rows
我正在嘗試在R中編寫一個嵌套的for循環,但遇到了問題。 我已進行了盡可能多的研究,但找不到(或理解)我需要的幫助。 我對R還是很陌生,因此,如果對這種循環有任何建議,或者如果有一種更簡單,更優雅的方法,將不勝感激!
我已經為許多位置(我稱它們為站點)生成了每日溫度文件,文件列的設置如下:
年月日unix_time site_a site_b site_c site_d ...等
對於每個站點(在每列內),我要遍歷溫度值並創建一個新列(或新數據框),並使用與這些溫度范圍相對應的數字(生理速率)。 (例如,低於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預先感謝!
使用向量化的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))))))))})
安德列斯(Andres)的答案對於apply
部分非常有用,它可以使您遍及所有“溫度”列。 我被困在這里,沒有R的副本(正在工作)進行實驗,但是我懷疑您是否創建了一個截止值的向量xcut <- c(0,6.25,8.75,.11.25,...
然后做
x <- xcut[(which(x>xcut))]
您將擁有更簡單的代碼,並且也更容易編輯。 (注意:我添加了0
值以避免x
值小的問題:-))
這是僅使用邏輯的另一種方法:
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)
我發現在這樣的情況下, 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.