0

I have two data.frames firstdf and secondf, (example data below.) I’m trying to create a function that would output results like the ExampleList data I have below. I want to create a list of lists, where it grabs the first row entries from firstdf and puts their values in the thing and test fields in exampleList, then grabs the first 3 values from the otherthing field in seconddf, concatenates them together, and saves them in the otherthing field in exampleList, then moves on to the next row in firstdf and the next 3 rows in seconddf. Loops are a little tricky for me, so tips are definitely appreciated.

data:

dput(firstdf)
structure(list(thing = structure(1:3, .Label = c("thing1", "thing2", 
"thing3"), class = "factor"), test = structure(1:3, .Label = c("test1", 
"test2", "test3"), class = "factor")), .Names = c("thing", "test"
), row.names = c(NA, -3L), class = "data.frame")

dput(seconddf)
    structure(list(otherthing = structure(c(4L, 5L, 6L, 7L, 8L, 9L, 
    1L, 2L, 3L), .Label = c("thing10", "thing11", "thing12", "thing4", 
    "thing5", "thing6", "thing7", "thing8", "thing9"), class = "factor"), 
        other = structure(c(9L, 6L, 7L, 2L, 3L, 1L, 8L, 4L, 5L), .Label = c("fads", 
        "oiu", "qwer", "rewa", "rewq", "sfas", "sfwg", "tre", "xdfs"
        ), class = "factor")), .Names = c("otherthing", "other"), row.names = c(NA, 
    -9L), class = "data.frame")

And output:

 dput(ExampleList)
list(structure(list(thing = "thing1", test = "test1", otherthing = c("thing4", 
"thing5", "thing6")), .Names = c("thing", "test", "otherthing"
)), structure(list(thing = "thing2", test = "test2", otherthing = c("thing7", 
"thing8", "thing9")), .Names = c("thing", "test", "otherthing"
)), structure(list(thing = "thing3", test = "test3", otherthing = c("thing10", 
"thing11", "thing12")), .Names = c("thing", "test", "otherthing"
)))
[[1]]
[[1]]$thing
[1] "thing1"

[[1]]$test
[1] "test1"

[[1]]$otherthing
[1] "thing4" "thing5" "thing6"


[[2]]
[[2]]$thing
[1] "thing2"

[[2]]$test
[1] "test2"

[[2]]$otherthing
[1] "thing7" "thing8" "thing9"


[[3]]
[[3]]$thing
[1] "thing3"

[[3]]$test
[1] "test3"

[[3]]$otherthing
[1] "thing10" "thing11" "thing12"
Aramis7d
  • 2,444
  • 19
  • 25
user3476463
  • 3,967
  • 22
  • 57
  • 117

1 Answers1

0

You could use Map, the multivariate version of lapply (with split for otherthing). The first parameter is a function to applied to multiple parameters that will be iterated on in parallel, so

ExampleList <- Map(list, 
    thing = as.character(firstdf$thing), 
    test = as.character(firstdf$test), 
    otherthing = split(as.character(seconddf[[1]]), rep(1:3, each = 3)))

str(ExampleList)

## List of 3
##  $ thing1:List of 3
##   ..$ thing     : chr "thing1"
##   ..$ test      : chr "test1"
##   ..$ otherthing: chr [1:3] "thing4" "thing5" "thing6"
##  $ thing2:List of 3
##   ..$ thing     : chr "thing2"
##   ..$ test      : chr "test2"
##   ..$ otherthing: chr [1:3] "thing7" "thing8" "thing9"
##  $ thing3:List of 3
##   ..$ thing     : chr "thing3"
##   ..$ test      : chr "test3"
##   ..$ otherthing: chr [1:3] "thing10" "thing11" "thing12"
alistaire
  • 42,459
  • 4
  • 77
  • 117
  • Thank you, your suggestion works very well with my sample data. However my real data secondddf data is much longer and I'm getting the following error when I try your suggestion. Is there a way to modify your code to deal with the longer seconddf? Error: Warning message: In split.default(as.character(seconddf[[1]]), rep(length(firstdf$thing), : data length is not a multiple of split variable – user3476463 Jan 24 '17 at 04:59
  • Check out `?split`. From the example I assumed you wanted it split in threes, but if that differs for your real data, you need to construct a vector to split by that is the same length as the vector to split, with a unique value for each split you'd like to end up with. – alistaire Jan 24 '17 at 05:08