How can I rename the elements of the list within another list using for loop?
When working with lists, it's often useful to map
functions over them rather than using loops. For this case, you can use an indexed map to modify the names of each sub-list element according to the index of its parent list:
library(purrr)
renamed_list <- imap(list, function(l, n) {names(l) <- paste0(names(l), n) ; l})
str(renamed_list)
#> List of 2
#> $ :List of 2
#> ..$ x1:'data.frame': 2 obs. of 2 variables:
#> .. ..$ a: num [1:2] 1 2
#> .. ..$ b: num [1:2] 3 4
#> ..$ y1:'data.frame': 2 obs. of 3 variables:
#> .. ..$ a: num [1:2] 1 2
#> .. ..$ b: num [1:2] 3 4
#> .. ..$ c: num [1:2] 5 6
#> $ :List of 2
#> ..$ x2:'data.frame': 2 obs. of 2 variables:
#> .. ..$ a: num [1:2] 7 8
#> .. ..$ b: num [1:2] 9 10
#> ..$ y2:'data.frame': 2 obs. of 4 variables:
#> .. ..$ a: num [1:2] 11 12
#> .. ..$ b: num [1:2] 13 14
#> .. ..$ c: num [1:2] 15 16
#> .. ..$ d: num [1:2] 17 18
There's a bit to unpack in the imap
line, so I'll go through it. imap
takes a list (in this case your list <- list(fir, sec)
) and the names or indices of its elements, and applies some function to each element that utilizes the names/indices.
I condensed it down to one line above, but the function I'm applying to each list is:
function(l, n) {
names(l) <- paste0(names(l), n)
return(l)
}
l
is a sub-list, and n
is the name (if named) or index (if not named) of the parent list. We take the names of our sub-list and append the name/index to whatever was already there. In this case, the parent lists don't have named elements, so we append the index and get sub-lists with elements named x1, y1
, x2, y2
, and so on.
Change name of element names in loop through lists
Try this:
a <- list(1, 2)
b <- list(3, 4)
for (my.list in c("a", "b")) {
x <- get(my.list)
names(x) <- c("element1", "element2")
assign(my.list, x)
}
Function for renaming specific elements of list
Modified function:
renamefct <- function(element_names, element) {
for(i in element_names) {
names(element[[i]]$namednum) <- c("Var1", "Var2", "Var3", "Var4")
}
return(element)
}
This works:
mylist <- renamefct(element_names1, mylist)
names(mylist[["type_1"]]$namednum)
[1] "Var1" "Var2" "Var3" "Var4"
Rename by list() variable name rather than index in R
Don't define x.list
, just iterate over the names:
fit <- vector("list",3)
for ( i in c("x1","x2","x3") ) fit[[i]] <- summary(lm(frame$y ~ frame[[i]]))
Save lm
s instead. It's likely that you'll want more than the summary, so just save the lm
s:
xs <- c("x1","x2","x3")
xs <- setNames(xs,xs)
fit_lm <- lapply(xs,function(i)lm(frame$y ~ frame[[i]]))
You can look at summary
with lapply(fit_lm,summary)
, but also look at coefficients, with
sapply(fit_lm,`[[`,"coefficients")
# x1 x2 x3
# (Intercept) 0.1417501 0.2974165 0.25085281
# frame[[i]] 0.2318912 -0.1468433 -0.08783857
Change list items in for loop in R
for(item in myList)
creates a new object called item
If you want to refer to the items from the list, it would be better to do it by calling either their position with myList[1]
, or their name with myList[["a"]]
.
You can for-loop through the list by using the index (as one of the comments suggested).
myList <- list(a=1, b=2, c=4, d=5)
for(i in 1:length(myList)){
myList[i] <- 3
}
myList
But I would recomment a vector approach. Check this out:
myList <- list(a=1, b=2, c=1, d=5)
myList=='1'
myList[myList=='1']=3
myList
myList[names(myList)=='a']=9
myList
Now you do not have any redundant variables.
This is actually the recommended approach in R. For-loops are too computationally expensive.
Name output from a for loop using a list in R
When I am moving along multiple variables, I tend to use an index (or name) instead. This should work for you:
recording_list <- recording_summary$Original_filename # chr [1:100]
clipID_list <- recording_summary$ClipID # int [1:100]
for (idx in 1:length(recording_list)){
wavIN <- readWave(recording_list[idx], from=120, to=301, units="seconds")
writeWave(wavIN, paste0(clipID_list[idx], ".wav"))
rm(wavIN)
}
Renaming dataframe column elements using a for loop
The for
loop does not work because it iterates over each element of the vector and R does work "by value", not "by reference", this means, if you modify "x" R creates a new "memory slot" but does NOT modify the original vector.
Just remove the first character instead of looping over each row/element which is BTW bad practice - use a vectorized version instead that "loops" implicitly:
max.length <- max(nchar(as.character(Anscombe$set)))
Anscombe$set2 <- substr(Anscombe$set, 2, max.length) # remove first character
The result is a character type (I have not touched set
so that you can see the difference):
> Anscombe
set x y set2
1 x1 10 8.04 1
5 x1 11 8.33 1
9 x1 12 10.84 1
14 x2 13 8.74 2
18 x2 6 6.13 2
22 x2 5 4.74 2
23 x3 10 7.46 3
27 x3 11 7.81 3
31 x3 12 8.15 3
36 x4 8 7.71 4
40 x4 8 5.25 4
44 x4 8 6.89 4
PS: Also note the Anscombe$set
is a factor type (not a string) which uses a numeric internally, see:
> str(Anscombe)
'data.frame': 12 obs. of 4 variables:
$ set : Factor w/ 8 levels "x1","x2","x3",..: 1 1 1 2 2 2 3 3 3 4 ...
$ x : num 10 11 12 13 6 5 10 11 12 8 ...
$ y : num 8.04 8.33 10.84 8.74 6.13 ...
That's why I use convertion with as.character
above...
Building a list in a loop in R - getting item names correct
It works if you don't use the append
command:
mybiglist <- list()
for(i in 1:5){
a <- runif(10)
b <- rnorm(16)
c <- rbinom(8, 5, i/10)
name <- paste('item:',i,sep='')
tmp <- list(uniform=a, normal=b, binomial=c)
mybiglist[[name]] <- tmp
}
# List of 5
# $ item:1:List of 3
# ..$ uniform : num [1:10] 0.737 0.987 0.577 0.814 0.452 ...
# ..$ normal : num [1:16] -0.403 -0.104 2.147 0.32 1.713 ...
# ..$ binomial: num [1:8] 0 0 0 0 1 0 0 1
# $ item:2:List of 3
# ..$ uniform : num [1:10] 0.61 0.62 0.49 0.217 0.862 ...
# ..$ normal : num [1:16] 0.945 -0.154 -0.5 -0.729 -0.547 ...
# ..$ binomial: num [1:8] 1 2 2 0 2 1 0 2
# $ item:3:List of 3
# ..$ uniform : num [1:10] 0.66 0.094 0.432 0.634 0.949 ...
# ..$ normal : num [1:16] -0.607 0.274 -1.455 0.828 -0.73 ...
# ..$ binomial: num [1:8] 2 2 3 1 1 1 2 0
# $ item:4:List of 3
# ..$ uniform : num [1:10] 0.455 0.442 0.149 0.745 0.24 ...
# ..$ normal : num [1:16] 0.0994 -0.5332 -0.8131 -1.1847 -0.8032 ...
# ..$ binomial: num [1:8] 2 3 1 1 2 2 2 1
# $ item:5:List of 3
# ..$ uniform : num [1:10] 0.816 0.279 0.583 0.179 0.321 ...
# ..$ normal : num [1:16] -0.036 1.137 0.178 0.29 1.266 ...
# ..$ binomial: num [1:8] 3 4 3 4 4 2 2 3
Rename elements of list based on condition
Here is an option - loop over the list
with map
and do the changes with a condition (if/else
) (Here, we are using errorlist
as it is more general. It also works with samplelist)
library(dplyr)
library(purrr)
map(errorlist, ~ if(ncol(.x) == 1 && names(.x) == 'sample_0')
setNames(.x, 'sampling') else
rename_with(.x, ~ 'sampling', matches('sample_1')))
-output
$Alpha
# A tibble: 5 × 2
sample_0 sampling
<dbl> <dbl>
1 3 NA
2 NA 8
3 7 5
4 9 4
5 2 NA
$Beta
# A tibble: 5 × 2
sample_0 sampling
<dbl> <dbl>
1 2 3
2 9 7
3 NA 9
4 3 3
5 7 NA
$Gamma
# A tibble: 5 × 1
sampling
<dbl>
1 NA
2 NA
3 4
4 6
5 3
$Delta
# A tibble: 5 × 1
error
<dbl>
1 3
2 7
3 9
4 3
5 NA
Update
Based on the OP's comments
lapply(errorlist, \(x) {
nm1 <- stringr::str_subset(names(x), "^sample_\\d+$")
i1 <- which.max(as.numeric(stringr::str_extract(nm1,
"(?<=sample_)\\d+")))
if(length(i1) > 0) names(x)[names(x) == nm1[i1]] <- "sampling"
x})
-output
$Alpha
# A tibble: 5 × 3
sample_0 sample_1 sampling
<dbl> <dbl> <dbl>
1 3 NA 7
2 NA 8 3
3 7 5 5
4 9 4 NA
5 2 NA NA
$Beta
# A tibble: 5 × 3
sample_0 sample_1 sampling
<dbl> <dbl> <dbl>
1 2 3 4
2 9 7 2
3 NA 9 6
4 3 3 4
5 7 NA 6
$Gamma
# A tibble: 5 × 2
sample_0 sampling
<dbl> <dbl>
1 NA 3
2 NA 7
3 4 3
4 6 NA
5 3 8
$Delta
# A tibble: 5 × 1
error
<dbl>
1 3
2 7
3 9
4 3
5 NA
Related Topics
Replicate a List to Create a List-Of-Lists
Can You Pass a Vector to a Vararg: Vector to Sprintf
Freezing Header and First Column Using Data.Table in Shiny
Ggplot2 Add a Legend for Several Stat_Functions
R: Replacing Foreign Characters in a String
Ggplot2': Label Values of Barplot That Uses 'Fun.Y="Mean"' of 'Stat_Summary'
R Output Without [1], How to Nicely Format
How to Create a Variable of Rownames
Navlistpanel: Make Tabs Sequentially Active in Shiny App
How to Install R-Packages Not in the Conda Repositories
How Is Data Passed from Reactive Shiny Expression to Ggvis Plot
Determine Season from Date Using Lubridate in R
How to Add Gaussian Curve to Histogram Created with Qplot
Tukeys Post-Hoc on Ggplot Boxplot
R: Further Subset a Selection Using the Pipe %>% and Placeholder