Perhaps something like this is what you're after?
df1 <- data.frame(year = 2006, x = 1:3)
df2 <- data.frame(year = 2007, x = 4:6)
df3 <- data.frame(year = 2006, x = 7:9)
df4 <- data.frame(year = 2007, x = 10:12)
l1 <- list(x2006 = df1, x2007 = df2)
l2 <- list(x2006 = df3, x2007 = df4)
lapply(names(l1), function(x) cbind(l1[[x]], l2[[x]]))
####
[[1]]
year x year x
1 2006 1 2006 7
2 2006 2 2006 8
3 2006 3 2006 9
[[2]]
year x year x
1 2007 4 2007 10
2 2007 5 2007 11
3 2007 6 2007 12
There may be other functions that would be more appropriate than cbind()
such as merge()
, but this should get you on the right path. This obviously assumes that you have named your lists and those names are consistent between l1
and l2
.
EDITED TO ADD SOME MORE CONTEXT
There are a few key assumptions that make this work. Those assumptions are:
- Your list objects have
names
- The
names
in each list are consistent between lists
So, what are the names
I'm referring to? If you look at the code about where I define l1
, you'll see x2006 = df1
and x2007 = df2
. I'm defining two objects in that list, df1
and df2
with two names x2006
and x2007
.
You can check the names of the list by asking for the names()
:
names(l1)
####
[1] "x2006" "x2007"
The other key assumption is that you can index objects in a list by their name, using the [[
function. For example:
l1[["x2006"]]
####
year x
1 2006 1
2 2006 2
3 2006 3
So what we're doing with the lapply
function is that we're iterating over the names of l1
, defining an anonymous function, and then using the [[
function to index the two list objects l1
and l2
. We're currently using cbind
as the function, but you can replace cbind
with almost any other function.
As I mentioned above, this assumes that the names
are the same between the two or more list objects. For example, this does not work:
#change the names of the l2 list
names(l2) <- c("foo", "bar")
lapply(names(l1), function(x) cbind(l1[[x]], l2[[x]]))
####
Error in data.frame(..., check.names = FALSE) :
arguments imply differing number of rows: 3, 0
The names
however do not have to be in the same order. That's where the benefit of the [[
function comes in. To wit:
#Fix names on l2 again
names(l2) <- c("x2006", "x2007")
l2reverse <- list(x2007 = df4, x2006 = df3)
all.equal(
lapply(names(l1), function(x) cbind(l1[[x]], l2[[x]])),
lapply(names(l1), function(x) cbind(l1[[x]], l2reverse[[x]]))
)
####
[1] TRUE