Вложенный цикл в R: столбцы, затем строки - PullRequest
0 голосов
/ 14 февраля 2012

Я пытаюсь написать вложенный цикл for в R, но сталкиваюсь с проблемами.Я исследовал как можно больше, но не могу найти (или понять) нужную мне помощь.Я довольно новичок в 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]){<br> if (data$point_a[i]<6.25) data$rate_point_a[i]<--1.33 else<br> if (data$point_a[i]>=6.25 && data$point_a[i]<8.75) data$rate_point_a[i]<-0.99 else<br> if (data$point_a[i]>=8.75 && data$point_a[i]<11.25) data$rate_point_a[i]<-3.31 else<br> if (data$point_a[i]>=11.25 && data$point_a[i]<13.75) data$rate_point_a[i]<-2.56 else<br> if (data$point_a[i]>=13.75 && data$point_a[i]<16.25) data$rate_point_a[i]<-1.81 else<br> if (data$point_a[i]>=16.25 && data$point_a[i]<18.75) data$rate_point_a[i]<-2.78 else<br> if (data$point_a[i]>=18.75 && data$point_a[i]<21.25) data$rate_point_a[i]<-3.75 else<br> if (data$point_a[i]>=21.25 && data$point_a[i]<23.75) data$rate_point_a[i]<-1.98 else<br> if (data$point_a[i]>=23.75 && data$point_a[i]<26.25) data$rate_point_a[i]<-0.21<br> }

Приведенный выше код дает мне новый столбец с именем "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  ...

Наверное, я не знаю, как заставить выражение «если еще» ссылаться на правильные места.Я знаю, что не могу добавить столбцы «скорость» в существующий фрейм данных, так как это увеличит мой ncol по мере прохождения цикла, поэтому нужно поместить их в другой фрейм данных (хотя не думаю, что это мойГлавная проблема).У меня будет много, много точек для проработки, и я бы предпочел не делать их по одному, поэтому моя попытка вложенного цикла.

Любая помощь будет высоко ценится.Вот ссылка на некоторые примеры данных, если это полезно.http://dl.dropbox.com/u/17903768/AVHRR_output.txt Заранее спасибо!

Ответы [ 4 ]

1 голос
/ 14 февраля 2012

Ответ Андреса отлично подходит для части apply, которая поможет вам пройти через все столбцы «температуры». Я застрял здесь без копии R (на работе), чтобы поэкспериментировать с, но я подозреваю, если вы создадите вектор ваших значений отсечки xcut <- c(0,6.25,8.75,.11.25,...
и просто сделай
x <- xcut[(which(x>xcut))]
у вас будет намного более простой код, а также его легче редактировать. (примечание: я добавил значение 0, чтобы избежать проблем с маленькими значениями x :-))

1 голос
/ 14 февраля 2012

Используйте 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))))))))})
0 голосов
/ 14 февраля 2012

Я считаю, что 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)
0 голосов
/ 14 февраля 2012

вот еще один способ с использованием только логики:

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