我想返回表中每列的唯一值的计数。例如,如果我有表:
Testdata <- data.frame(var_1 = c("a","a","a"), var_2 = c("b","b","b"), var_3 = c("c","d","e"))
var_1 | var_2 | var_3
a | b | c
a | b | d
a | b | e
我希望输出为:
Variable | Unique_Values
var_1 | 1
var_2 | 1
var_3 | 3
我尝试使用独特的功能玩循环,例如
for(i in names(Testdata)){
# Code using unique function
}
但我怀疑有一种更简单的方法。
答案 0 :(得分:25)
您可以使用apply
:
apply(Testdata, 2, function(x) length(unique(x)))
# var_1 var_2 var_3
# 1 1 3
答案 1 :(得分:6)
在dplyr
:
Testdata %>% summarise_all(funs(n_distinct(.)))
答案 2 :(得分:5)
这实际上是对@Ananda Mahto评论的改进。它不适合评论,所以我决定添加作为答案。
sapply
实际上比lapply
略快,并以更紧凑的形式提供输出,就像apply
的输出一样。
实际数据的测试运行结果:
> start <- Sys.time()
> apply(datafile, 2, function(x)length(unique(x)))
symbol. date volume
1371 261 53647
> Sys.time() - start
Time difference of 1.619567 secs
>
> start <- Sys.time()
> lapply(datafile, function(x)length(unique(x)))
$symbol.
[1] 1371
$date
[1] 261
$volume
[1] 53647
> Sys.time() - start
Time difference of 0.07129478 secs
>
> start <- Sys.time()
> sapply(datafile, function(x)length(unique(x)))
symbol. date volume
1371 261 53647
> Sys.time() - start
Time difference of 0.06939292 secs
datafile
有大约350万行。
引用帮助文本:
sapply是一个用户友好的版本,默认情况下是lapply的包装器 返回一个向量,矩阵,或者,如果是simplify =“array”,则返回一个数组if 适当的,通过应用simplify2array()。 sapply(x,f,simplify = FALSE,USE.NAMES = FALSE)与lapply(x,f)相同。
答案 3 :(得分:3)
使用lengths
- 函数:
lengths(lapply(Testdata, unique))
# var_1 var_2 var_3
# 1 1 3
答案 4 :(得分:1)
这是另一种选择:
aggregate(values ~ ind, unique(stack(Testdata)), length)
# ind values
# 1 var_1 1
# 2 var_2 1
# 3 var_3 3
这要求列为character
。
答案 5 :(得分:1)
在此,我已使用dplyr
和tidyr
来计算(使用您的Testdata
数据框):
Testdata %>%
gather(var, value) %>%
distinct() %>%
count(var)
# # A tibble: 3 × 2
# var n
# <chr> <int>
# 1 var_1 1
# 2 var_2 1
# 3 var_3 3
答案 6 :(得分:0)
我刚尝试了所有的解决方案,上面的两个解决方案没有使用聚合和tidyr的解决方案,但其中两个使用不起作用。我认为使用数据表是一个不错的选择,
setDT(Testdata)[, lapply(.SD, uniqueN), .SDcols=c("var_1","var_2","var_3")]
# var_1 var_2 var_3
# 1: 1 1 3
我试图将它们相互比较
library(microbenchmark)
Mycomp = microbenchmark(
apply = apply(Testdata, 2, function(x)length(unique(x))),
lapply = lapply(Testdata, function(x)length(unique(x))),
sapply = sapply(Testdata, function(x)length(unique(x))),
#base = aggregate(values ~ ind, unique(stack(Testdata)), length),
datatable = setDT(Testdata)[, lapply(.SD, uniqueN), .SDcols=c("var_1","var_2","var_3")],
times=50
)
#Unit: microseconds
# expr min lq mean median uq max neval cld
# apply 163.315 176.678 192.0435 181.7915 192.047 608.859 50 b
# lapply 138.217 147.339 157.9684 153.0640 165.829 254.145 50 a
# sapply 160.338 169.124 178.1486 174.3965 185.548 203.419 50 b
# datatable 667.937 684.650 698.1306 696.0160 703.390 874.073 50 c
答案 7 :(得分:0)
proc sql;
select
case
when frac = '1/12' then 0.083
when frac = '1/6' then 0.167
...
end as frac_as_num
from df
;
quit;
答案 8 :(得分:0)
collapse::fNdistinct
需要一个 data.frame
。
library(collapse)
fNdistinct(Testdata)
# var_1 var_2 var_3
# 1 1 3
而且速度很快。具有 10000 行和 10000 列的数据:
Testdata = data.frame(replicate(1e4, sample(letters[1:sample(26, 1)], 1e4, replace = TRUE)))
system.time(fNdistinct(Testdata))
# user system elapsed
# 0.38 0.00 0.37