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

Posted

技术标签:

【中文标题】计算每行数据表中的唯一值【英文标题】:count unique values in each row data table 【发布时间】:2015-09-01 13:20:05 【问题描述】:

我有一个类似的数据表

    col1     col2     col3    col4
1:    a        a        a       2
2:    b        b        a       4.4
3:    w        w        s       6.3

我想在不运行 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

我正在计算每行中 col1、col2、col3 的唯一值并存储在计数列中。我如何在 1 行中做到这一点?

【问题讨论】:

如何将length(unique()) 应用于矩阵减去 col4 的转置版本? 这是一种循环方式,但它涉及将数据表转换为矩阵,然后再转换回数据表。我确信必须有某种方法可以仅将其作为数据表。但无法弄清楚。 【参考方案1】:

这可能有用:

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)))

输出:

> 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

data.table 解决方案

在本例中使用data.table 语法会有点棘手。

首先我创建一个 id 列,用于分组:

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

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

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

输出:

> 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

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

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

如果我们结合 @Frank 和 @Tensibai 的 cmets,这应该是最快的(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

【讨论】:

最好打电话给col1...col3 而不是1:3 @Frank 哇哦!我不知道这个功能。我目前正在使用 1.9.4。我将更新 data.table 并重试。我会更新答案。谢谢。 我将删除 unlist(strplit()) 并将 paste0() 替换为 c(),我是否错过了一些关于此的内容? @Tensibai 谢谢你。是的,它好多了。我会更新答案。谢谢。在我让它工作之前,我正在检查/测试很多东西。 @Frank 我不想故意使用 .SD,因为根据我从作者那里读到的报告,它需要很长时间才能运行。我想要一个使用 just by 的解决方案。并且使用.I1:nrow(df2) 几乎相同,尽管我同意使用.I 更紧凑(不确定速度)。我在代码上方的评论中提到了 uniqueN 需要 data.table 1.9.5+【参考方案2】:

以下内容如何:

dt <- CJ(1:5,1:3,1:4,1:2)
dt[, cnt:=apply(dt, 1, function(r) length(unique(r)))]

或者如果您只想保留具有唯一条目的行,您可以尝试

dt <- CJ(1:5,1:3,1:4,1:2)
dt[apply(dt, 1, function(r) length(unique(r))==ncol(dt))]

【讨论】:

以上是关于计算每行数据表中的唯一值的主要内容,如果未能解决你的问题,请参考以下文章

列中每行具有唯一值的 Python/CSV 唯一行

计算每行中真实值的数量

像 Qlik 一样计算 pandas 数据框中的列中的唯一值?

Excel:如何为唯一组合分配值/检查大型数据集中的唯一组合

在 Pandas 数据框中查找唯一值,无论行或列位置如何

在大熊猫数据框中计算每行历史值的最有效方法是啥?