I have a list with several data frames of different taxa. The df's for the different taxa are of different length and have different names for columns with the "same information", e.g. "abundance", "abund", "individuals". I show you an example:
spiders <- data.frame(plot = c(1,2,3),
abundance = c(1,4,8),
habitat = c(rep("forest", 3)))
bugs <- data.frame(plot = c(1,2,3),
abund = c(1,4,8))
birds<- data.frame(plot = c(1,2,3),
individuals= C(1,4,8),
habitat = c(rep("forest", 3)),
method = c(rep("visual", 3)))
lst <- list("spiders" = spiders, "bugs" = bugs, "birds" = birds)
show(lst)
$spiders
plot abundance habitat
1 1 1 forest
2 2 4 forest
3 3 8 forest
$bugs
plot abund
1 1 1
2 2 4
3 3 8
$birds
plot individuals habitat method
1 1 1 forest visual
2 2 4 forest visual
3 3 8 forest visual
In my original list, I have much more dfs.. What I want to do is to iterate through the dfs and change all colnames with "abund" or "individuals" to "abundance", if not already.
If I have a list with just one df lst %>% map(rename, abundance = abund)
works fine, but with more dfs and different colnames, it says:
error: Can't rename columns that don't exist. x Column
abund
doesn't exist.
I tried several codes:
lst %>% set_names(~sub("abund", "abundance", names(.x)))
lst %>% set_names(~sub("abund", "abundance", .x))
and many others with map_if
, map_at
, rename_if
, rename_at
, etc., but nothing worked.
dplyr::rename_with()
applies a function to each column name. In that function we can check if the name contains “abund” or “individuals” with grepl()
and then those columns get renamed. The columns that don’t contain the strings we are looking for technically also get renamed, but they receive their old name again, so nothing is changed there.
library(dplyr)
library(purrr)
map(lst, ~ rename_with(., ~ ifelse(
grepl("abund|individuals", .), "abundance", .
)))
#> $spiders
#> plot abundance habitat
#> 1 1 1 forest
#> 2 2 4 forest
#> 3 3 8 forest
#>
#> $bugs
#> plot abundance
#> 1 1 1
#> 2 2 4
#> 3 3 8
#>
#> $birds
#> plot abundance habitat
#> 1 1 1 forest
#> 2 2 4 forest
#> 3 3 8 forest
#> 4 1 1 visual
#> 5 2 4 visual
#> 6 3 8 visual
Instead of using tidyverse style anonymous functions we can use the new base R anonymous function style in order to make the code a bit more comprehensible.
map(lst, \(df) rename_with(df, \(name) ifelse(
grepl("abund|individuals", name), "abundance", name
)))
#> $spiders
#> plot abundance habitat
#> 1 1 1 forest
#> 2 2 4 forest
#> 3 3 8 forest
#>
#> $bugs
#> plot abundance
#> 1 1 1
#> 2 2 4
#> 3 3 8
#>
#> $birds
#> plot abundance habitat
#> 1 1 1 forest
#> 2 2 4 forest
#> 3 3 8 forest
#> 4 1 1 visual
#> 5 2 4 visual
#> 6 3 8 visual