1

I am trying to produce a script which has functions that can produce a list of statistics and writes them to data.frame, which can in turn be written to a csv file if needed. This would be to check that individual .las files in a directory meet contractual obligations and produce 'reports' on them (so to speak).

I have read in the data as a LAScatalog and am trying to access the classification information. I have tried to follow the advice given in Lasinfo like task with lascatalog lidR and tried to read in the individual files (see below):

las_directory <- 'path/to/las/directory' # las_catalog <- readLAScatalog() already exists in the code using this path
las_catagories <- lapply(las_directory, function(las_directory) {
las <- readLAS(las_directory, select = "c")
table(las$Classification)})

This is for use within a function with a similar structure to the example in the 'Make a high level function' section in this vignette https://cran.r-project.org/web/packages/lidR/vignettes/lidR-LAScatalog-engine.html#making-a-valid-function-for-catalog_apply

It produced this error:

Error in as.list.default(X) : no method for coercing this S4 class to a vector

I tried to change the function to the following to see if it made any difference:

las_catagories <- lapply(las_directory, function(las) {
las <- readLAS(las_directory, select = "c")
table(las$Classification)})

and it produced the following error:

Error in streamLAS.character(files, ofile = "", select, filter) : File(s) are not las or laz

I subsequently tried to test it on a single file:

las_file <- paste0(las_directory, "7935.las")
las <- readLAS(las_file, select = "c")
table(las$Classification)})

which worked and produce the following:

>las_catagories
[[1]]
      1        2        3        4        5        7       19
1469047 26217559  2076049    34974     6353   255433 13398340

I then retried with the las_directory after ensuring it contained the right file path and it produced the error Error: File does not exist. I used las_list <- list.file(las_directory) and it produced the following error again:

Error in streamLAS.character(files, ofile = "", select, filter) : File(s) are not las or laz

I then tried to define the function separately:

select_classifications <- function(las){
las <- readLAS(las, select = 'c')
table(las$Classifications)
}

and use a for loop to apply it to the las_directory:

for (las in las_directory) {
select_classifications(las)
}

which returned the same as the previous error (file(s) are not las or laz so I then tested it on a a single las_file again, and again it worked fine. I then tried lapply again:

for (las in las_directory {
lapply(select_classifications(las))
}

and it produced the following error:

Error in lapply(select_classifications(las)):
argument "FUN" is missing, with no default

Finally I tried to iterate through the directory using the following code:

las_files <- list.files('path/to/directory')
for (file_name in las_files) {
data_list[[file_name]] <- readLAS(file_name)

which produced the error Error: File does not exist

Sorry for the long question, but I wanted to show all my attempts either for someone to point out how ridiculous they are, or to ensure that everyone's time is saved. Just to note, there is over 4000 .las files, all around 1gb in size. I am using future::plan(multisession, workers = 8) to process this. It means automation is key rather than having to go through them all by hand! I have also tried using whitebox tools, but currently there are restrictions on new R packages from our IT department (for reasons...) and it is waiting in the ticket queue to be given permission.

Thanks for reading all the way to the end!

1 Answer 1

0

Sounds like you misunderstand how to loop through files of a folder in R. Nothing related to lidR. You have several options.

you can loop

las_files <- list.files('path/to/directory', full.names = T)
for (file_name in las_files) {
las <- readLAS(file_name)
do_smothing(las)
}

you can apply (which is like a loop)

las_files <- list.files('path/to/directory', full.names = T)
lapply(las_files, function(x) {
las <- readLAS(x)
do_something(las)
})

You can use the lidR engine

do_something = function(chunk)
{
  las = readLAS(chunk)
  if (is.empty(las) return(NULL)
  # do something
}

ctg = readLAScatalog("path/to/directory", chunk_buffer = 0)
catalog_apply(ctg, do_something)
3
  • thank you very much for you help and for providing different options. The first option produced NULL. My 'do_somthing' was: las_catagories <- las$Classification print(las_catagories) The third option worked perfectly, thank you, as did the second option. I really appreciate it. Would you be able to specify what gave it away that I didn't understand how to loop with R? As I am struggling to pick out why your options worked but mine didn't (though putting lapply in a for loop I now see is very odd...). Sep 29 at 14:37
  • You missed full.names = TRUE. All my options are correct but written without testing so maybe not copy pastable as is.
    – JRR
    Sep 29 at 14:41
  • Ah, I had misunderstood what list.files('path/to/directory)' provided then. Thank you. Regarding your code, thank you; I realise that you're not helping to just write my code for me and that I need to adapt it to suit my own needs. I think I need to spend a bit more time rereading the vignettes and going through some tutorials about how to select data/headers in different classes. Thank you again, I really appreciate your help! Sep 29 at 14:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.