I did several attempts to add a specific column to data frames resp. lists within a list, but all *apply() attempts failed to preserve the names of the data frames.
For example for list l,
l <- list(alpha=data.frame(1:3), bravo=data.frame(4:6), charly=data.frame(7:9))
> l
$`alpha`
X1.3
1 1
2 2
3 3
$bravo
X4.6
1 4
2 5
3 6
$charly
X7.9
1 7
2 8
3 9
I want the initial letters of the lists' names as a second id column. I tried these attempts who give me basically what I want:
lapply(seq_along(l), function(x) cbind(l[[x]], id=substr(names(l)[x], 1, 1)))
# or
lapply(seq_along(l), function(x) data.frame(l[[x]], id=substr(names(l)[x], 1, 1)))
# [[1]]
# X1.3 id
# 1 1 a
# 2 2 a
# 3 3 a
#
# [[2]]
# X4.6 id
# 1 4 b
# 2 5 b
# 3 6 b
#
# [[3]]
# X7.9 id
# 1 7 c
# 2 8 c
# 3 9 c
but the inner lists have lost their names. Option USE.NAMES=TRUE from lapply() documentation didn't work.
I also tried these two attempts, but they failed even worse.
lapply(seq_along(l), function(x) mapply(cbind, l[[x]], id=substr(names(l)[x], 1, 1),
SIMPLIFY=FALSE))
rapply(l, function(x) cbind(x, id=substr(names(l)[x], 1, 1)), how="list")
I know I could do this like so:
l1 <- lapply(seq_along(l), function(x) cbind(l[[x]], id=substr(names(l)[x], 1, 1)))
names(l1) <- names(l)
or do a for loop:
for(i in seq_along(l)) {
l[[i]] <- data.frame(l[[i]], id=substr(names(l)[i], 1, 1))
}
but I'd like to know whether an *apply() solution could be improved to bring the expected output, which would be:
$`alpha`
X1.3 id
1 1 a
2 2 a
3 3 a
$bravo
X4.6 id
1 4 b
2 5 b
3 6 b
$charly
X7.9 id
1 7 c
2 8 c
3 9 c
Try Map
Map(`[<-`, l, "id", value = substr(names(l), 1, 1))
#$alpha
# X1.3 id
#1 1 a
#2 2 a
#3 3 a
#$bravo
# X4.6 id
#1 4 b
#2 5 b
#3 6 b
#$charly
# X7.9 id
#1 7 c
#2 8 c
#3 9 c
The first argument is a function. Map then applies the function "to the first elements of each ... argument, the second elements, the third elements, and so on.", see ?mapply.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With