Question

I have three string variables of the length 2 and I need to get (a) all possible permutations of the three variables (keeping the order of strings within each variable fixed), (b) all possible variable pairs. Small number of variables allows me to do it manually, but I was wondering if there is a more elegant and concise way of solving this.

It is currently coded as:

egen perm1 = concat(x1 x5 x9)
egen perm2 = concat(x1 x9 x5)
egen perm3 = concat(x5 x1 x9)
egen perm4 = concat(x5 x9 x1)
egen perm5 = concat(x9 x5 x1)
egen perm6 = concat(x9 x1 x5)

gen tuple1 = substr(perm1,1,4)
gen tuple2 = substr(perm2,3,4)
gen tuple3 = substr(perm3,1,4)
gen tuple4 = substr(perm4,3,4)...

An abstract from a resulting table illustrates the desired outcome:

 +----+----+----+--------+--------+--------+--------+--------+--------+--------+--------+
| x1 | x5 | x9 | perm1  | perm2  | perm3  | perm4  | perm5  | perm6  | tuple1 | tuple2 |
+----+----+----+--------+--------+--------+--------+--------+--------+--------+--------+
| 01 | 05 | 09 | 010509 | 010905 | 050109 | 050901 | 090501 | 090105 |   0105 |   0509 |
+----+----+----+--------+--------+--------+--------+--------+--------+--------+--------+
Was it helpful?

Solution

Neat question. I don't know if there's a "built in" way to do permutations, but the following should do it.

You want to loop over all your variables, but make sure that don't get duplicates. As the dimensions increase this gets tricky. What I do it loop over the same list and each time remove the current counter from counter space of the nested loop.

Unfortunately, this still requires you to write each loop structure, but this should be easy enough to cut-paste-find-replace.

clear
set obs 100
generate x1 = "01"
generate x5 = "05"
generate x9 = "09"

local vars x1 x5 x9
local i = 0
foreach a of varlist `vars' {
    local bs : list vars - a
    foreach b of varlist `bs' {
        local cs : list bs - b
        foreach c of varlist `cs' {
            local ++i
            egen perm`i' = concat(`a' `b' `c')
        }
    }
}

Edit: Re-reading the question, I'm not clear on what you want (since row1_1 isn't one of your concated variables. Note that if you really want the "drop one" permutations, then just remove one variable from the concat call. This is because "n permute n" is the same as "n permute n-1". That is, there are 6 3-item permutations of 3 items. There are also 6 2-item permutations of 3 items. So

egen perm`i' = concat(`a' `b')
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top