4

How can I append/ push data into union dynamically?

For instance, I have 4 data sets to merge,

mydata <- union(data1, data2, data3, data4)

But sometimes I have less than 4 while sometimes more than that.

Any ideas how can I solve this problem?

smci
  • 32,567
  • 20
  • 113
  • 146
Run
  • 54,938
  • 169
  • 450
  • 748
  • 2
    What is this `union` function? The `base::union` only takes 2 vectors as input. –  May 07 '15 at 07:21
  • 1
    @Pascal I think he used it to illustrate his problem. – zx8754 May 07 '15 at 07:22
  • What? He wants to generalize `union()` to N-arguments, moreover where N changes dynamically. The 'dynamic' part is a red-herring. – smci May 07 '15 at 07:27
  • Wherever the `data[0-9]...` are coming from, since their length is unknown, why not just pass in a list-of-datasets? Then for a length-N list, we only need ceil(log2(N)) `union()` calls. – smci May 07 '15 at 07:29
  • 1
    @smci I get [your point about dynamic](http://stackoverflow.com/a/13650955/680068), I am not going to question the "why" he is doing this way. Still an interesting question. – zx8754 May 07 '15 at 07:35
  • @smci `why not just pass in a list-of-datasets? Then for a length-N list, we only need ceil(log2(N)) union() calls.` it would be helpful if you can show me some example codes - I just started coding in R a couple of weeks ago... – Run May 07 '15 at 13:59
  • @teelou: I don't understand how your code can (or should) be generating a varying number of datasets in the first place. Instead of generating distinct datasets, let's create and append to a list-of-datasets. Better still, can we do away with the individual datasets and add them to the union immediately when they are created? – smci May 08 '15 at 01:28

2 Answers2

4

Make some reproducible data:

#dummy data
data1 <- data.frame(x=letters[1:3])
data2 <- data.frame(x=letters[2:4])
data3 <- data.frame(x=letters[5:7])

We can use rbind with unique in a string then evaluate:

#get list of data frames to merge, update pattern as needed
data_names <- ls()[grepl("data\\d",ls())]
data_names <- paste(data_names,collapse=",")

#make command string
myUnion <- paste0("unique(rbind(",data_names,"))")

#evaluate
eval(parse(text=myUnion))

EDIT:

Here is another better/simpler way, using do.call:

unique(do.call("rbind",lapply(objects(pattern="data\\d"),get)))
zx8754
  • 52,746
  • 12
  • 114
  • 209
2

You could roll your own function like vunion defined below. Not sure if this actually works, my [R] got a bit stale ;)

Basically, you accept any number of arguments (hence ...) and make use of those as if they were packed in a list. Just choose and remove the first 2 items from that list, calculate their union, append them to the list, repeat.

vunion <- function(...){
  data <- list(...)
  n <- length(data)
  if(n > 2){
    u <- list(t(union(data[[1]], data[[2]])))
    return(do.call(vunion, as.list(c(tail(data, -2), u))))
  } else {
    return(union(data[[1]], data[[2]]))
  }
}
Tedil
  • 1,935
  • 28
  • 32