テーブルのすべての列の一意の値の数を返したいのですが。たとえば、テーブルがある場合:
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
}
しかし、もっと簡単な方法があると思います。
apply
を使用できます:
apply(Testdata, 2, function(x) length(unique(x)))
# var_1 var_2 var_3
# 1 1 3
dplyr
内:
Testdata %>% summarise_all(n_distinct)
????
(完全な構文について知りたい人のために。
dplyr >0.8.0
purrr
構文を使用:
Testdata %>% summarise_all(list(~n_distinct(.)))
dplyr <0.8.0
:
Testdata %>% summarise_all(funs(n_distinct(.)))
)
ここにある複数の列の要約の詳細については、 https://dplyr.tidyverse.org/reference/summarise_all.html
これは実際には@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のラッパーであり、ベクトル、行列、または単純化= "配列"の場合は、必要に応じて、単純化配列2を適用して配列を返します。 sapply(x、f、simplemate = FALSE、USE.NAMES = FALSE)は、lapply(x、f)と同じです。
lengths
functionを使用する:
lengths(lapply(Testdata, unique))
# var_1 var_2 var_3
# 1 1 3
ここに代替があります:
aggregate(values ~ ind, unique(stack(Testdata)), length)
# ind values
# 1 var_1 1
# 2 var_2 1
# 3 var_3 3
これには、列がcharacter
である必要があります。
ここでは、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
私はすべての解決策を試してみましたが、上記の解決策の2つは1つの集計とtidyrの解決策では機能しませんでしたが、2つの解決策では機能しませんでした。データテーブルを使用することをお勧めします。
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
library(purrr)
Testdata %>% map_dbl(n_distinct)
var_1 var_2 var_3
1 1 3
# in your format
Testdata %>% map_dbl(n_distinct)%>%melt(value.name = "unique_counts")
unique_counts
var_1 1
var_2 1
var_3 3