How can I remove multiple elements from a list based on their names?

I have 891 tif images which I list them. I want to remove 10 specific images from the list based on their names (i.e., in the end I want my list to have 881 images). I tried many things but I am getting errors based on what I've tried. For example, my last try was:

l = list.files("path", pattern = ".tif$", full.names = FALSE)

remove <- c("pop", "tirs", "agbh", "ndvi", "road", "poi", "blue", "nir", "swir", "red")

l[l != remove]

I get this error: comparison (2) is possible only for atomic vectors.

Another try was:

l[l != c("pop", "tirs", "agbh", "ndvi", "road", "poi", "blue", "nir", "swir", "red")]

I got this warning: longer object length is not multiple of shorter object lenght.

How can I remove multiple elements from a list based on their names?

in general you would use something like

l[ ! l %in% remove ]

as this is vectorised on the l, and will exclude any member of l that is not in the remove list.
However , I would expect your remove list to contain items ending .tif and yours dont ? "pop.tif" for example
If "pop" is not meant to be the complete name but just a detectable part then you will need to use some form of regex, probably most conveniently through the stringr library to do the matching as = \ != and %in% are all going to check that two items are the same or different, and not look to see if they have common or differing parts

@nirgrahamuk I changed the elements in remove by adding .tif and then I used your code l[ ! l %in% remove ]. In the Global environment, the l still has 891 elements but in the console the list prints 881. Is this correct?

I am asking this because if I remove the elements manually, one by one, by typing for example l <- l[-1] (for the agbh.tif element to be removed), then the l on the Global envirnment has 890 elements.

I think you need to assign the output to replace the original l.

l <- l[ ! l %in% remove ]

# full.names doesn't mean the name with the file
# extension stripped; it means the file name without the 
# full path name; I'm going to use the full
# path so that reprex will be able to find it
# call it v for vector, not l for list
(v = list.files("/Users/ro/projects/demo",pattern = ".csv$", full.names = FALSE))
#>  [1] "bio.csv"        "" "datitot.csv"    "dframe.csv"    
#>  [5] "foo.csv"        "grist.csv"      "msptemps.csv"   "mtcars.csv"    
#>  [9] "s.csv"          "t3.csv"         "ukgas.csv"

# specify the file names to remove including the 
# extension

(remove <- c("foo.csv","grist.csv","mtcars.csv"))
#> [1] "foo.csv"    "grist.csv"  "mtcars.csv"

# use set difference to find members of v that
# are not in remove

#> [1] "bio.csv"        "" "datitot.csv"    "dframe.csv"    
#> [5] "msptemps.csv"   "s.csv"          "t3.csv"         "ukgas.csv"

Created on 2023-05-26 with reprex v2.0.2

1 Like
(v <- list.files("/Users/ro/projects/demo",pattern = ".csv$", full.names = FALSE))
#>  [1] "baz.csv"        "bio.csv"        "" "datitot.csv"   
#>  [5] "dframe.csv"     "foo.csv"        "grist.csv"      "msptemps.csv"  
#>  [9] "mtcars.csv"     "s.csv"          "t3.csv"         "ukgas.csv"
(r <- c("baz","bar","foo"))
#> [1] "baz" "bar" "foo"
identical(v,v[!v %in% r])
#> [1] TRUE

If the file names are pop.tif, etc. trying to exclude pop won't work.

This topic was automatically closed 7 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.