Problem creating Loop function for images

Hello everyone, hope you can help me trying to avoid DRY in my code.

I am trying to evaluate the sea temperature. I have results with this
first code, but I want to improve with a loop function, just I don't know how to convert to "for function".

CODE

#open image
library(oce)
library(ncdf4)

fn <- "C:/images/gertmo/figure_sun1.nc"
vart <- nc_open(fn)
ray1 <- ncvar_get(vart,"degrees")
nc_close(vart)
final1 <- ray1[c(ocean)]    #Here "ocean" was defined in other object before but is a constant in all files"

fn <- "C:/images/gertmo/figure_sun2.nc"
vart <- nc_open(fn)
ray2 <- ncvar_get(vart,"degrees")
nc_close(vart)
final2 <- ray2[c(ocean)]    
..
The following for 30 days.
 #then using "cbind", to get a file with all the variables "final"

SUN2015 <- cbind(final,final2,...)

The files are in the same folder, and in numerically order.

Thanks so much for your kind suggestions.
I hope.

I can't test this without your files, but I think this should work. You use map_dfc to iterate a function over a sequence of integers from 1 to 30, using sprintf to create the string for the filename from the integer at each step. map_dfc specifies that you want the results of the iterating to be bound by column into a new data frame.

library(dplyr)
library(purrr)

SUN2015 <- map_dfc(seq(30), function(i) {

  require(oce)
  require(ncdf4)

  filename <- sprintf("C:/images/gertmo/figure_sun%s.nc", x)
  vart <- nc_open(filename)
  ray2 <- ncvar_get(vart,"degrees")
  nc_close(vart)
  final <- ray[c(ocean)]

  return(final)

})

In base R, you could do this with lapply and then cbind.

SUN2015_list <- lapply(seq(30), function(i) {

  require(oce)
  require(ncdf4)

  filename <- sprintf("C:/images/gertmo/figure_sun%s.nc", x)
  vart <- nc_open(filename)
  ray2 <- ncvar_get(vart,"degrees")
  nc_close(vart)
  final <- ray[c(ocean)]

  return(final)

})

SUN2015 <- do.call(cbind, SUN2015_list)
1 Like

Hello ulfelder, Thanks for your soon reply.
I'm trying to run your code, I wrote these lines:


loop_list <- map_dfc(seq(27),function(i){
  i=3:29
  require(oce)
  require(ncdf4)
  filename <- sprintf("C:/images/february/modis2019/A2019033.L3m_DAY_CHL.x_chlor_a%s.nc",x)
  vart <- nc_open(filename)
  ray <- ncvar_get(vart,"degrees")
  nc_close(vart)
  final <- ray[c(ocean)] 
  return(final)
})

ocean2019 <- do.call(cbind, loop_list)

Getting the error:
Error in sprintf("C:/images/february/modis2019/A2019033.L3m_DAY_CHL.x_chlor_a%s.nc", :
object 'x' not find

There some points that I had to explain before:

  1. In the folder exist 29 files numerically order, but from the third file is where calculations begin
    (the reason because I put i=3:29, I don't know if it is the correct way)
  2. The original name of the file is so long and just change in the numbers:
    1.A2019033.L3m_DAY_CHL.x_chlor_a.nc
    2.A2019035.L3m_DAY_CHL.x_chlor_a.nc
    3.A2019036.L3m_DAY_CHL.x_chlor_a.nc
    4.A2019037.L3m_DAY_CHL.x_chlor_a.nc
    The same for the following 27 days.
    Probably here I made another mistake with the module %s

I would like to upload the files but they are really big (each day 6MB more and less)
I really aprecciate your help and your comments. :pensive:
Thanks.
Chris.

@chrismike06, the problem in the call to sprintf is that you changed x to i at the top (i.e., function(i), so now there's no x to find. Change either the i to an x or vice versa and at least that part should work.

Oh, and now I also see what you're saying about the numbers. So, instead of seq(27), you'll need a vector of the numbers in your actual file names (035, 036, etc.). If the leading zero is always there, then you can do A20190%s and then use c(33:60) or whatever. If the leading zero switches to a 1 or it's not a straight sequence, you'll need to figure out a different way to create the vector of substrings to paste in with sprintf. All that function does is insert a string into another string, here x into the name, where %s is.

Also, if you use map_dfc, you don't need the do.call bit at the end. That concatenation is built into map_dfc. You only need that if you use lapply, which returns a list.

1 Like

@ulfelder good news!
Understand your explanation about the string and now the code run!
Although in a rustic mode it code works, is always welcome a new method for improving how to write codes, especially if after you want to reply with more data (This is really common in Ocean techniques where we work with a bunch of files)
Thanks so much for your soon reply!
Greetings!

Here the last modification and the solution.

loop_list <- map_dfc(c(33:59),function(i){

  require(oce)
  require(ncdf4)
  filename <- sprintf("images/february/modis2019/A20190%s.L3m_DAY_CHL.x_chlor_a.nc",i)
  vart <- nc_open(filename)
  ray <- ncvar_get(ncin,"degrees")
  nc_close(vart)
  final <- ray[c(ocean)]
  return(final)
})

1 Like

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