Help with a for loop

I managed to get the inner for loop to work, but I have not figured out to get the outer for loop to run. My objective of the for loop is to condense some data. My original data is in a format such that there are columns with data from a particular temperature. Each column is a different trial. There are various columns with data from the same temperature. I want the for loop to aggregate all of the same temperatures into one data frame for each temperature range. The title of each column is the temperature.trial#. So for example: cols 1-3 are Temp_30.1, Temp_30.2, Temp_30.3.

I know there is a way to condense this down, I just haven't gotten the code to work. I had to manually run the outer for loop. But here is the code:

Temprange<-c("30", "32", "34", "36", "38")
t<-grep(Temprange[1], names(data), value=TRUE)
t1<-data.frame(data[t[1]])
colnames(t1)<-paste("Temp_",Temprange[1], sep= "")
t30<-data.frame(rep("NA", times = count(t1)))

for (i in 1:length(t)){
  t30[,i+1]<-data[t[i]]
  colnames(t2)<-rep(paste("Temp_", Temprange[1], sep=""),times=i+1)
  #cat(i,"\n")  
}

#Temp 32 C
Temprange<-c("30", "32", "34", "36", "38")
t<-grep(Temprange[2], names(data), value=TRUE)
t1<-data.frame(data[t[2]])
colnames(t1)<-paste("Temp_",Temprange[2], sep= "")
t32<-data.frame(rep("NA", times = count(t1)))

for (i in 1:length(t)){
  t32[,i+1]<-data[t[i]]
  colnames(t32)<-rep(paste("Temp_", Temprange[2], sep=""),times=i+1)
  #cat(i,"\n")  
}

#Temp 34 C
Temprange<-c("30", "32", "34", "36", "38")
t<-grep(Temprange[3], names(data), value=TRUE)
t1<-data.frame(data[t[3]])
colnames(t1)<-paste("Temp_",Temprange[3], sep= "")
t34<-data.frame(rep("NA", times = count(t1)))

for (i in 1:length(t)){
  t34[,i+1]<-data[t[i]]
  colnames(t34)<-rep(paste("Temp_", Temprange[3], sep=""),times=i+1)
  #cat(i,"\n")  
}

#Temp 36 C
Temprange<-c("30", "32", "34", "36", "38")
t<-grep(Temprange[4], names(data), value=TRUE)
t1<-data.frame(data[t[4]])
colnames(t1)<-paste("Temp_",Temprange[4], sep= "")
t36<-data.frame(rep("NA", times = count(t1)))

for (i in 1:length(t)){
  t36[,i+1]<-data[t[i]]
  colnames(t36)<-rep(paste("Temp_", Temprange[4], sep=""),times=i+1)
  #cat(i,"\n")  
}

#Temp 38 C
Temprange<-c("30", "32", "34", "36", "38")
t<-grep(Temprange[5], names(data), value=TRUE)
t1<-data.frame(data[t[5]])
colnames(t1)<-paste("Temp_",Temprange[5], sep= "")
t38<-data.frame(rep("NA", times = count(t1)))

for (i in 1:length(t)){
  t38[,i+1]<-data[t[i]]
  colnames(t38)<-rep(paste("Temp_", Temprange[5], sep=""),times=i+1)
  #cat(i,"\n")  
}

The main issue I'm having is not knowing how to create a new data frame for each of my new temperatures in the for loop named according to the temperature. Any help would be greatly appreciated!

What I have tried that doesn't work is this:

Temprange<-c("30", "32", "34", "36", "38")
for (jj in 1:5){
t<-grep(Temprange[jj], names(data), value=TRUE)
t1<-data.frame(data[t[jj]])
colnames(t1)<-paste("Temp_",Temprange[jj], sep= "")
for (i in 1:length(t)){
  t30[,i+1]<-data[t[i]]
  colnames(t2)<-rep(paste("Temp_", Temprange[jj], sep=""),times=i+1)
}
}

If I understand correctly what you are trying to do, I would not use for loops at all. You can iterate over a vector containing your different temperatures with the map() function from purrr and use the select() function from dplyr to get the columns. You end up with a list with each element being one of the data frames.

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(purrr)

#invent data
Df <- data.frame(Temp_30.1 = 1:10, Temp_30.2 = 2:11, Temp_30.3 = 3:12,
                 Temp_32.1 = 11:20, Temp_32.2 = 12:21, Temp_32.3 = 13:22,
                 Temp_34.1 = 21:30, Temp_34.2 = 22:31, Temp_34.3 = 23:32)

Temps <- c("30", "32", "34")

MyFunc <- function(Nm) {
   select(Df, contains(Nm))
 }

Frames <-  map(Temps, MyFunc)

Frames[[1]]
#>    Temp_30.1 Temp_30.2 Temp_30.3
#> 1          1         2         3
#> 2          2         3         4
#> 3          3         4         5
#> 4          4         5         6
#> 5          5         6         7
#> 6          6         7         8
#> 7          7         8         9
#> 8          8         9        10
#> 9          9        10        11
#> 10        10        11        12
Frames[[2]]
#>    Temp_32.1 Temp_32.2 Temp_32.3
#> 1         11        12        13
#> 2         12        13        14
#> 3         13        14        15
#> 4         14        15        16
#> 5         15        16        17
#> 6         16        17        18
#> 7         17        18        19
#> 8         18        19        20
#> 9         19        20        21
#> 10        20        21        22

Created on 2021-05-29 by the reprex package (v0.3.0)

Edit:
The call to map could also be

Frames <-  map(Temps, ~ select(Df, contains(.x)))

It is just a matter of taste.

I tried that and it works beautifully and very fast, thank you very much!

Would you be able to explain in more detail how it works?
If I understand correctly, you created a function called MyFunc, and I'm not sure what Nm is.
But this function then selects from the DF data frame and selects out things that contain Nm?
and then you use the map function with my desired temps as the list and the newly created function as the function to iterate by?

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.