Reputation: 511
I want to add individual elements of a char vector as columns to a list of data.frames. I can do it manually, but is there a more elegant lapply-way?
# Create sample dfs
set.seed(1)
df1 <- data.frame("one" = sample(1:10,10,replace=TRUE),
"two" = sample(1:10,10,replace=TRUE))
df2 <- data.frame("three" = sample(1:10,10,replace=TRUE),
"four" = sample(1:10,10,replace=TRUE))
df3 <- data.frame("five" = sample(1:10,10,replace=TRUE),
"six" = sample(1:10,10,replace=TRUE))
# Combine them to list
dflist = list("df1"=df1,"df2"=df2,"df3"=df3)
# add labelling column
dflist$df1["label"] <- "a"
dflist$df2["label"] <- "b"
dflist$df3["label"] <- "c"
# With lapply I can only add either "a", "b" or "c"
dflist = list("df1"=df1,"df2"=df2,"df3"=df3)
labvec <- c("a","b","c")
lapply(dflist,function(x) cbind(x,labvec[2])) # I have to select 1, 2 or 3.
Asked differently: Could i also index over "labvec" with lapply?
Upvotes: 1
Views: 41
Reputation: 887691
Using tidyverse
with map2
library(tidyverse)
map2(dflist, labvec, ~ .x %>%
mutate(label = .y))
#$df1
# one two label
#1 3 3 a
#2 4 2 a
#3 6 7 a
#4 10 4 a
#5 3 8 a
#6 9 5 a
#7 10 8 a
#8 7 10 a
#9 7 4 a
#10 1 8 a
#$df2
# three four label
#1 10 5 b
#2 3 6 b
#3 7 5 b
#4 2 2 b
#5 3 9 b
#6 4 7 b
#7 1 8 b
#8 4 2 b
#9 9 8 b
#10 4 5 b
#$df3
# five six label
#1 9 5 c
#2 7 9 c
#3 8 5 c
#4 6 3 c
#5 6 1 c
#6 8 1 c
#7 1 4 c
#8 5 6 c
#9 8 7 c
#10 7 5 c
Upvotes: 1
Reputation: 26363
You could use Map
Map(`[<-`, x = dflist, i = "label", value = labvec)
#$df1
# one two label
#1 1 3 a
#2 2 1 a
#3 2 3 a
#$df2
# three four label
#1 3 1 b
#2 2 1 b
#3 2 1 b
#$df3
# five six label
#1 3 2 c
#2 2 3 c
#3 3 3 c
x
, i
and value
are arguments of the function `[<-`
, that we usually not name as in iris['Species2'] <- "a_string_column"
, where
x
: iris
i
: 'Species2'
value
: "a_string_column"
The same idea as above but here we use an anonymous function with three arguments (might be easier to read):
Map(function(data, label, value) {data[label] <- value; data},
data = dflist,
label = "label",
value = labvec)
data
set.seed(1)
df1 <- data.frame("one" = sample(3,replace=TRUE),
"two" = sample(3,replace=TRUE))
df2 <- data.frame("three" = sample(3,replace=TRUE),
"four" = sample(3,replace=TRUE))
df3 <- data.frame("five" = sample(3,replace=TRUE),
"six" = sample(3,replace=TRUE))
# Combine them to list
dflist = list("df1"=df1,"df2"=df2,"df3"=df3)
Upvotes: 3
Reputation: 8374
A solution with lapply()
and the use of dplyr::mutate()
.
library(dplyr)
dflist <- lapply(1:length(dflist), function(i) {
dflist[[i]] %>%
mutate(label = letters[i])
})
# lapply(dflist, head, 2)
# [[1]]
# one two label
# 1 3 3 a
# 2 4 2 a
#
# [[2]]
# three four label
# 1 10 5 b
# 2 3 6 b
#
# [[3]]
# five six label
# 1 9 5 c
# 2 7 9 c
Note that this is just "forcing" the lapply()
, I mean, it's basically a for
loop not that well hidden.
Upvotes: 1