0

I have a table of events with an indication when they happen. They are already ordered by time.

   events <- data.frame(name=c("sow", "water", "harvest"), time=c("March", "May", "June"), stringsAsFactors = FALSE)

I want to get a list of all 2-element permutations of events which happened after each other (without the duplicates).

earlier    later
sow        water
sow        harvest
water      harvest

I know a couple of functions in R for getting some kind of combinations or permutations, but I have not found any that consider the order of appearance within the input.

Is there a function which does this, or do I have to implement my own?

Rumi P.
  • 1,688
  • 3
  • 23
  • 31
  • If the events are in order of time could you do: `t(combn(events$name, 2))`? – Ben Feb 04 '20 at 17:45
  • @Ben yes they are ordered, or at least easily orderable since I have the column. What is the t function? I don't recall having seen it before, and searches for `r t` don't return much relevant stuff. – Rumi P. Feb 04 '20 at 17:50
  • @Ben Ah, I see it, thanks. And is `combn` guaranteed to always return combinations such that the item with the "smaller number" is listed first, or is this an implementation detail that might theoretically change between versions? I don't see the order mentioned in the help file (which I opened in the console this time :) ) – Rumi P. Feb 04 '20 at 17:54
  • @Ben I would be happy to see it as an answer. The downside of the order changing someday is purely theoretical, and it is much more concise than the existing answers. – Rumi P. Feb 04 '20 at 18:07
  • Does this answer your question? [How to generate all possible combinations of vectors without caring for order?](https://stackoverflow.com/questions/12245213/how-to-generate-all-possible-combinations-of-vectors-without-caring-for-order) – Joseph Wood Feb 05 '20 at 09:54
  • @JosephWood no, it is an entirely different problem being solved in that other question. – Rumi P. Feb 21 '20 at 10:17

3 Answers3

2

I came to a similar conclusion using lapply

df <- lapply(1:nrow(events), function(x) {
              expand.grid(events$name[x], events$name[(x+1):nrow(events)])})
do.call(rbind, df[-nrow(events)])
#>    Var1    Var2
#> 1   sow   water
#> 2   sow harvest
#> 3 water harvest

Allan Cameron
  • 147,086
  • 7
  • 49
  • 87
2

Assuming your column is already in the desired order, you can use combn function and transpose:

t(combn(events$name, 2))

     [,1]    [,2]     
[1,] "sow"   "water"  
[2,] "sow"   "harvest"
[3,] "water" "harvest"
Ben
  • 28,684
  • 5
  • 23
  • 45
0

After some thinking, I realized that this is relatively easy to implement when using expand.grid on numbers.

events <- data.frame(name=c("sow", "water", "harvest"), month=c("3", "5", "6"), stringsAsFactors = FALSE)

ordered.pairs <- function(events.names.in.order) {

n <- length(events.names.in.order)
numbers.to.use <- 1:n
doubled.indices <- expand.grid(numbers.to.use, numbers.to.use)
doubled.indices <- doubled.indices[doubled.indices$Var1 < doubled.indices$Var2,]

event.pairs <- data.frame(earlier=events.names.in.order[doubled.indices$Var1], later=events.names.in.order[doubled.indices$Var2])

return(event.pairs)

}
Rumi P.
  • 1,688
  • 3
  • 23
  • 31