web-dev-qa-db-ja.com

すべての列の一意の値をカウントする

テーブルのすべての列の一意の値の数を返したいのですが。たとえば、テーブルがある場合:

 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
 }

しかし、もっと簡単な方法があると思います。

18
Zfunk

applyを使用できます:

apply(Testdata, 2, function(x) length(unique(x)))
# var_1 var_2 var_3 
#     1     1     3
30
sgibb

dplyr内:

Testdata %>% summarise_all(n_distinct)

????

(完全な構文について知りたい人のために。

dplyr >0.8.0purrr構文を使用:

Testdata %>% summarise_all(list(~n_distinct(.)))

dplyr <0.8.0

Testdata %>% summarise_all(funs(n_distinct(.)))

ここにある複数の列の要約の詳細については、 https://dplyr.tidyverse.org/reference/summarise_all.html

10
leerssej

これは実際には@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)と同じです。

5
Tapajit Dey

lengthsfunctionを使用する:

lengths(lapply(Testdata, unique))

# var_1 var_2 var_3 
#     1     1     3 
4
zx8754

ここに代替があります:

aggregate(values ~ ind, unique(stack(Testdata)), length)
#     ind values
# 1 var_1      1
# 2 var_2      1
# 3 var_3      3

これには、列がcharacterである必要があります。

1
Matthew Plourde

ここでは、dplyrtidyrを使用してカウントしています(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
1
Megatron

私はすべての解決策を試してみましたが、上記の解決策の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
0
user6376316
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
0
Vinay