计算每行数据表中的唯一值

use*_*020 1 r data.table

我有一个数据表

    col1     col2     col3    col4
1:    a        a        a       2
2:    b        b        a       4.4
3:    w        w        s       6.3
Run Code Online (Sandbox Code Playgroud)

我想在不运行for循环的情况下获得类似下面的内容.

    col1     col2     col3    col4   count
1:     a        a        a        2      1
2:     b        b        a        4.4    2
3:     w        w        s        6.3    2
Run Code Online (Sandbox Code Playgroud)

我计算每行中col1,col2,col3的唯一值并存储在count列中.我如何在一行中完成此操作?

Lyz*_*deR 7

这可能有用:

data.frame解决方案

df <- read.table(header=T, text='   col1     col2     col3    col4
1    a        a        a       2
2    b        b        a       4.4
3    w        w        s       6.3')

#one line using apply    
df$count <- apply(df[1:3], 1, function(x) {length(unique(x))})
Run Code Online (Sandbox Code Playgroud)

输出:

> df
  col1 col2 col3 col4 count
1    a    a    a  2.0     1
2    b    b    a  4.4     2
3    w    w    s  6.3     2
Run Code Online (Sandbox Code Playgroud)

data.table解决方案

data.table在这个例子中使用语法会有点棘手.

首先,我创建一个id列,通过该列到group_by:

#convert original df to data.table
df2 <- as.data.table(df)
df2[, id := 1:nrow(df2) ]
Run Code Online (Sandbox Code Playgroud)

然后我使用我自制的luna函数来计算独特元素的长度:

luna <- function(x)   length(unique(unlist(strsplit(x,''))))
df2[, count := luna(paste0(col1, col2, col3)), by=id ]
Run Code Online (Sandbox Code Playgroud)

输出:

> df2
   col1 col2 col3 col4 id count
1:    a    a    a  2.0  1     1
2:    b    b    a  4.4  2     2
3:    w    w    s  6.3  3     2
Run Code Online (Sandbox Code Playgroud)

或者正如@Tensibai在评论中提到的那样,这要快得多:

df2 <- as.data.table(df)
df2[, id := 1:nrow(df2) ]
luna <- function(x)   length(unique(x))

df2[, count2 := luna(c(col1, col2, col3)), by=id ]

> df2
   col1 col2 col3 col4 id count2
1:    a    a    a  2.0  1      1
2:    b    b    a  4.4  2      2
3:    w    w    s  6.3  3      2
Run Code Online (Sandbox Code Playgroud)

如果我们将@ Frank和@Tensibai的评论结合起来,这应该是最快的(data.table 1.9.5+):

df2 <- as.data.table(df)
df2[, id := 1:nrow(df2) ]

#not run
#works only in data.table >= 1.9.5
df2[, count2 := uniqueN(c(col1, col2, col3)), by=id ]
#not run
Run Code Online (Sandbox Code Playgroud)