数据框中一列唯一值的数量R

26

对于一个数据框 df,我需要找到 some_col 的唯一值。尝试了以下代码:

length(unique(df["some_col"]))

但是这并没有给出预期的结果。然而,length(unique(some_vector)) 在向量上运行并给出了预期的结果。

在创建数据框之前有一些先前的步骤。

df <- read.csv(file, header=T)
typeof(df) #=> "list"
typeof(unique(df["some_col"])) #=> "list"
length(unique(df["some_col"])) #=> 1 
6个回答

27

尝试使用[[而不是[[返回一个list(实际上是一个data.frame),[[返回一个vector

df <- data.frame( some_col = c(1,2,3,4),
                  another_col = c(4,5,6,7) )

length(unique(df[["some_col"]]))
#[1] 4

class( df[["some_col"]] )
[1] "numeric"

class( df["some_col"] )
[1] "data.frame"

由于list只有一个元素,即使该元素包含多个值,您也会得到1的值(1个列)。


10

您需要使用

length(unique(unlist(df[c("some_col")])))

当您通过df[c("some_col")]或df["some_col"]调用列时,它会将其作为列表提取。使用unlist可以将其转换为向量,您可以轻松处理它。当您通过df$some_col调用列时,它会将数据列作为向量提取。


这里的每个人都会欣赏真正的帮助,而不是聪明的回答。这是不必要的。标记它。 - Mandar
很抱歉冒犯了您。我只是想指出您在不需要(当然您可以)使用unlist()时使用了“需要”这个词(而我认为这是一个不好的选择),因为[[是可用的。 - s_baldur

5
我想你可能只是缺少一个 ,,试试:
length(unique(df[,"some_col"]))

回应评论:

df <- data.frame(cbind(A=c(1:10),B=rep(c("A","B"),5)))
df["B"]

输出:

B
1  A
2  B
3  A
4  B
5  A
6  B
7  A
8  B
9  A
10 B

并且

length(unique(df[,"B"])) 

输出:

[1] 1

这与原帖中发布的错误/不良输出相同

但是,加上逗号,

df[,"B"]

输出:

 [1] A B A B A B A B A B
Levels: A B

并且。
length(unique(df[,"B"])) 

现在根据操作员的要求,为您提供正确/期望的输出结果。在此示例中,输出结果为2。

[1] 2

原因在于df["some_col"]调用了一个data.frame,而对对象类data.frame使用length函数将计算该对象中的data.frames数量,该数量为1;而df[,"some_col"]返回一个vector,对vector使用length函数将正确返回该向量中元素的数量。因此你可以看到,逗号(,)起着至关重要的作用。


df["column name"] 和 [, "column name"] 是相同的。 - Mandar
实际上并不完全相同,这种差异足以使其正常工作。添加了测试以说明我的观点。 - JustGettinStarted
原因是 df["column name"] 是一个 data.frame,而对于一个 data.frame 类型的对象,调用 length 函数会计算其中的 data.frame 数量,即 1。而 df[,"column name"] 返回的是一个向量,调用 length 函数则能够正确地返回该向量中元素的数量。 - JustGettinStarted
感谢澄清 :) - Mandar

2

使用tidyverse

df %>% 
  select("some_col") %>% 
  n_distinct()

1

数据表(data.table)包含方便的简写uniqueN。请参阅文档

当x是原子向量时,uniqueN相当于length(unique(x));当x是数据框或数据表时,uniqueN相当于nrow(unique(x))。直接计算唯一行数,而不需要材料化中间唯一的数据表,因此更快且更节省内存。

您可以将其与数据框一起使用:

df <- data.frame(some_col = c(1,2,3,4),
                 another_col = c(4,5,6,7) )
data.table::uniqueN(df[['some_col']])

[1] 4

或者,如果您已经有一个数据表。
dt <- setDT(df)
dt[,uniqueN(some_col)]

[1] 4

0

这里还有另一个选择:

df %>% 
distinct(column_name) %>% 
count()

或者不使用tidyverse:

count(distinct(df, column_name))

在网上检查基准测试,你会发现distinct()很快。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接