Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I create a new column in a dataframe based on permutations of other columns?

Tags:

dataframe

r

Suppose I have a dataframe which looks like this:

    var1   var2   var3   var4  
a   TRUE   FALSE  TRUE   FALSE
b   TRUE   TRUE   TRUE   FALSE
c   FALSE  TRUE   FALSE  TRUE
d   TRUE   FALSE  FALSE  FALSE
e   TRUE   FALSE  TRUE   FALSE
f   FALSE  TRUE   FALSE  TRUE

I want to create a new column which assigns a to f to categories based on what permutation of TRUE and FALSE each has for the variables along the top.

In this simplified example, the result would look like:

    var1   var2   var3   var4    category
a   TRUE   FALSE  TRUE   FALSE      A
b   TRUE   TRUE   TRUE   FALSE      B
c   FALSE  TRUE   FALSE  TRUE       C
d   TRUE   FALSE  FALSE  FALSE      D
e   TRUE   FALSE  TRUE   FALSE      A
f   FALSE  TRUE   FALSE  TRUE       C

Notice that each unique permutation of TRUE and FALSE becomes a different category, and since a and e have the same permutation, they end up in the same category (A).

Is there an easy way to do this, which can work if there is a large number of variables along the top, and potentially not limited to TRUE and FALSE but also if the dataframe was filled with categories/numbers?

like image 720
Yang Li Avatar asked Dec 23 '22 21:12

Yang Li


1 Answers

You could do something like

## paste the rows together, creating a character vector
x <- do.call(paste, df)
## match it against itself and apply to 'LETTERS', and assign as new column
df$category <- LETTERS[match(x, x)]
df
#    var1  var2  var3  var4 category
# a  TRUE FALSE  TRUE FALSE        A
# b  TRUE  TRUE  TRUE FALSE        B
# c FALSE  TRUE FALSE  TRUE        C
# d  TRUE FALSE FALSE FALSE        D
# e  TRUE FALSE  TRUE FALSE        A
# f FALSE  TRUE FALSE  TRUE        C

The above code can be written as a one-liner if we use a named list as an environment. This avoids making any new assignments to the global environment.

df$category <- LETTERS[with(list(x = do.call(paste, df)), match(x, x))]

Data:

df <- structure(list(var1 = c(TRUE, TRUE, FALSE, TRUE, TRUE, FALSE), 
    var2 = c(FALSE, TRUE, TRUE, FALSE, FALSE, TRUE), var3 = c(TRUE, 
    TRUE, FALSE, FALSE, TRUE, FALSE), var4 = c(FALSE, FALSE, 
    TRUE, FALSE, FALSE, TRUE)), .Names = c("var1", "var2", "var3", 
"var4"), row.names = c("a", "b", "c", "d", "e", "f"), class = "data.frame")
like image 194
Rich Scriven Avatar answered Dec 26 '22 19:12

Rich Scriven