The number of unique elements of each row in a data frame in R

I have a dataframe as shown below:

Group1  Group2  Group3  Group4
A       B       A       B   
A       C       B       A   
B       B       B       B   
A       C       B       D   
A       D       C       A   

      

I want to add a new column to the dataframe that will have the number of unique elements in each row. Desired output:

Group1  Group2  Group3  Group4  Count
A       B       A       B       2
A       C       B       A       3
B       B       B       B       1
A       C       B       D       4
A       D       C       A       3

      

I can find a score like this for each line using

length(unique(c(df[,c(1,2,3,4)][1,])))

      

I want to do the same for all rows in a dataframe. I tried apply () with var = 1 but with no success. Also, it would be great if you could provide a more elegant solution .

+3


source to share


3 answers


We can use apply

c MARGIN =1

to loop over lines

df1$Count <- apply(df1, 1, function(x) length(unique(x)))
df1$Count
#[1] 2 3 1 4 3

      


Or using tidyverse

library(dplyr)
df1 %>%
    rowwise() %>%
    do(data.frame(., Count = n_distinct(unlist(.))))
# A tibble: 5 × 5
#   Group1 Group2 Group3 Group4 Count
#*  <chr>  <chr>  <chr>  <chr> <int>
#1      A      B      A      B     2
#2      A      C      B      A     3
#3      B      B      B      B     1
#4      A      C      B      D     4
#5      A      D      C      A     3

      




We can also use regex

to make it faster. It is based on the assumption that for each cell

there is only one character,
nchar(gsub("(.)(?=.*?\\1)", "", do.call(paste0, df1), perl = TRUE))
#[1] 2 3 1 4 3

      

More detailed explanation is given here

+4


source


duplicated

in R base:



df$Count <- apply(df,1,function(x) sum(!duplicated(x)))

#  Group1 Group2 Group3 Group4 Count
#1      A      B      A      B     2
#2      A      C      B      A     3
#3      B      B      B      B     1
#4      A      C      B      D     4
#5      A      D      C      A     3

      

+3


source


While there are some pretty big solutions here, you can also use data.table

:

DATA

df <- data.frame(g1 = c("A","A","B","A","A"),g2 = c("B", "C", "B","C","D"),g3 = c("A","B","B","B","C"),g4 = c("B","A","B","D","A"),stringsAsFactors = F)

      

Code:

EDIT . Added (.I) instead of 1: nrow (df) following David Arenberg's comment. Thanks for the valuable comments

library(data.table)
setDT(df)[, id := .I ]
df[, count := uniqueN(c(g1, g2, g3, g4)), by=id ]
df

      

Output

> df
   g1 g2 g3 g4 id count
1:  A  B  A  B  1     2
2:  A  C  B  A  2     3
3:  B  B  B  B  3     1
4:  A  C  B  D  4     4
5:  A  D  C  A  5     3

      

+2


source







All Articles