連続変数を3つの同じサイズのグループに分割/分割する必要があります。
データフレームの例
das <- data.frame(anim=1:15,
wt=c(181,179,180.5,201,201.5,245,246.4,
189.3,301,354,369,205,199,394,231.3))
(wt
の値に従って)分割された後、次のように新しい変数wt2
の下に3つのクラスが必要になります。
> das
anim wt wt2
1 1 181.0 1
2 2 179.0 1
3 3 180.5 1
4 4 201.0 2
5 5 201.5 2
6 6 245.0 2
7 7 246.4 3
8 8 189.3 1
9 9 301.0 3
10 10 354.0 3
11 11 369.0 3
12 12 205.0 2
13 13 199.0 1
14 14 394.0 3
15 15 231.3 2
これは大規模なデータセットに適用されます
これを試して:
split(das, cut(das$anim, 3))
wt
の値に基づいて分割する場合、
library(Hmisc) # cut2
split(das, cut2(das$wt, g=3))
とにかく、cut
、cut2
およびsplit
。
[〜#〜] updated [〜#〜]
グループインデックスを追加の列として使用する場合は、
das$group <- cut(das$anim, 3)
列が1、2、...などのインデックスである場合、
das$group <- as.numeric(cut(das$anim, 3))
更新済み
これを試して:
> das$wt2 <- as.numeric(cut2(das$wt, g=3))
> das
anim wt wt2
1 1 181.0 1
2 2 179.0 1
3 3 180.5 1
4 4 201.0 2
5 5 201.5 2
6 6 245.0 2
7 7 246.4 3
8 8 189.3 1
9 9 301.0 3
10 10 354.0 3
11 11 369.0 3
12 12 205.0 2
13 13 199.0 1
14 14 394.0 3
15 15 231.3 2
mltools パッケージのbin_data()
関数を使用した別のソリューションがあります。
library(mltools)
# Resulting bins have an equal number of observations in each group
das[, "wt2"] <- bin_data(das$wt, bins=3, binType = "quantile")
# Resulting bins are equally spaced from min to max
das[, "wt3"] <- bin_data(das$wt, bins=3, binType = "explicit")
# Or if you'd rather define the bins yourself
das[, "wt4"] <- bin_data(das$wt, bins=c(-Inf, 250, 322, Inf), binType = "explicit")
das
anim wt wt2 wt3 wt4
1 1 181.0 [179, 200.333333333333) [179, 250.666666666667) [-Inf, 250)
2 2 179.0 [179, 200.333333333333) [179, 250.666666666667) [-Inf, 250)
3 3 180.5 [179, 200.333333333333) [179, 250.666666666667) [-Inf, 250)
4 4 201.0 [200.333333333333, 245.466666666667) [179, 250.666666666667) [-Inf, 250)
5 5 201.5 [200.333333333333, 245.466666666667) [179, 250.666666666667) [-Inf, 250)
6 6 245.0 [200.333333333333, 245.466666666667) [179, 250.666666666667) [-Inf, 250)
7 7 246.4 [245.466666666667, 394] [179, 250.666666666667) [-Inf, 250)
8 8 189.3 [179, 200.333333333333) [179, 250.666666666667) [-Inf, 250)
9 9 301.0 [245.466666666667, 394] [250.666666666667, 322.333333333333) [250, 322)
10 10 354.0 [245.466666666667, 394] [322.333333333333, 394] [322, Inf]
11 11 369.0 [245.466666666667, 394] [322.333333333333, 394] [322, Inf]
12 12 205.0 [200.333333333333, 245.466666666667) [179, 250.666666666667) [-Inf, 250)
13 13 199.0 [179, 200.333333333333) [179, 250.666666666667) [-Inf, 250)
14 14 394.0 [245.466666666667, 394] [322.333333333333, 394] [322, Inf]
15 15 231.3 [200.333333333333, 245.466666666667) [179, 250.666666666667) [-Inf, 250)
代替なし cut2を使用。
das$wt2 <- as.factor( as.numeric( cut(das$wt,3)))
または
das$wt2 <- as.factor( cut(das$wt,3, labels=F))
@ ben-bolkerが指摘したように、これは占有ではなく等幅に分割されます。 quantiles
を使用すると、同等の占有率に近づくことができると思います
x = rnorm(10)
x
[1] -0.1074316 0.6690681 -1.7168853 0.5144931 1.6460280 0.7014368
[7] 1.1170587 -0.8503069 0.4462932 -0.1089427
bin = 3 #for 1/3 rd, 4 for 1/4, 100 for 1/100th etc
xx = cut(x, quantile(x, breaks=1/bin*c(1:bin)), labels=F, include.lowest=T)
table(xx)
1 2 3 4
3 2 2 3
ntile
からのdplyr
はこれを行うようになりましたが、NA
を使用すると奇妙に動作します。
ベースRで動作し、cut2
上記の解決策:
ntile_ <- function(x, n) {
b <- x[!is.na(x)]
q <- floor((n * (rank(b, ties.method = "first") - 1)/length(b)) + 1)
d <- rep(NA, length(x))
d[!is.na(x)] <- q
return(d)
}
cut
、明示的なブレークポイントが与えられない場合、値を同じ幅のビンに分割しますが、それらは一般に同数のアイテムを含みません:
x <- c(1:4,10)
lengths(split(x, cut(x, 2)))
# (0.991,5.5] (5.5,10]
# 4 1
Hmisc::cut2
およびggplot2::cut_number
は、分位点を使用します。データが十分に分散され、適切なサイズである場合、通常は同じサイズ(要素数)のグループを作成しますが、常にそうとは限りません。 mltools::bin_data
は異なる結果を与えることができますが、分位に基づいています。
これらの関数は、データに少数の個別の値が含まれる場合、常に適切な結果をもたらすとは限りません。
x <- rep(c(1:20),c(15, 7, 10, 3, 9, 3, 4, 9, 3, 2,
23, 2, 4, 1, 1, 7, 18, 37, 6, 2))
table(x)
# x
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
# 15 7 10 3 9 3 4 9 3 2 23 2 4 1 1 7 18 37 6 2
table(Hmisc::cut2(x, g=4))
# [ 1, 6) [ 6,12) [12,19) [19,20]
# 44 44 70 8
table(ggplot2::cut_number(x, 4))
# [1,5] (5,11] (11,18] (18,20]
# 44 44 70 8
table(mltools::bin_data(x, bins=4, binType = "quantile"))
# [1, 5) [5, 11) [11, 18) [18, 20]
# 35 30 56 45
ここで最適なソリューションが見つかった場合、これは明確ではありません。
bestビニングアプローチとは主観的な問題ですが、アプローチするための合理的な方法の1つは、予想されるビン周辺の分散を最小化するビンを探すことですサイズ。
(my)パッケージの関数smart_cut
cutr
は、そのような機能を提案します。ただし、計算量が多く、カットポイントと一意の値が少ないケースに予約する必要があります(通常、問題になる場合があります)。
# devtools::install_github("moodymudskipper/cutr")
table(cutr::smart_cut(x, list(4, "balanced"), "g"))
# [1,6) [6,12) [12,18) [18,20]
# 44 44 33 45
グループのバランスがとれていることがわかります。
実際、呼び出しの"balanced"
は、分散に基づく方法では不十分な場合に、必要に応じてビンを最適化または制限するカスタム関数に置き換えることができます。
equal_freq
from funModeling
は、ベクトルとビンの数を取ります(等しい頻度に基づいて)。
das <- data.frame(anim=1:15,
wt=c(181,179,180.5,201,201.5,245,246.4,
189.3,301,354,369,205,199,394,231.3))
das$wt_bin=funModeling::equal_freq(das$wt, 3)
table(das$wt_bin)
#[179,201) [201,246) [246,394]
# 5 5 5
bin
関数をOneR
パッケージのmethod = "content"
と共に使用することもできます:
library(OneR)
das$wt_2 <- as.numeric(bin(das$wt, nbins = 3, method = "content"))
das
## anim wt wt_2
## 1 1 181.0 1
## 2 2 179.0 1
## 3 3 180.5 1
## 4 4 201.0 2
## 5 5 201.5 2
## 6 6 245.0 2
## 7 7 246.4 3
## 8 8 189.3 1
## 9 9 301.0 3
## 10 10 354.0 3
## 11 11 369.0 3
## 12 12 205.0 2
## 13 13 199.0 1
## 14 14 394.0 3
## 15 15 231.3 2
均等に分散された3つのグループに分割する場合、答えは 上記のBen Bolkerの答え -use ggplot2::cut_number()
と同じです。完了のために、連続型からカテゴリ型(ビニング)に変換する3つの方法があります。
cut_number()
:観測数が(ほぼ)等しいn個のグループを作成しますcut_interval()
:等しい範囲のn個のグループを作成しますcut_width()
:観測値のビニングに等間隔のクォンタイルを使用するため、私の目的はcut_number()です。歪んだデータの例を次に示します。library(tidyverse)
skewed_tbl <- tibble(
counts = c(1:100, 1:50, 1:20, rep(1:10, 3),
rep(1:5, 5), rep(1:2, 10), rep(1, 20))
) %>%
mutate(
counts_cut_number = cut_number(counts, n = 4),
counts_cut_interval = cut_interval(counts, n = 4),
counts_cut_width = cut_width(counts, width = 25)
)
# Data
skewed_tbl
#> # A tibble: 265 x 4
#> counts counts_cut_number counts_cut_interval counts_cut_width
#> <dbl> <fct> <fct> <fct>
#> 1 1 [1,3] [1,25.8] [-12.5,12.5]
#> 2 2 [1,3] [1,25.8] [-12.5,12.5]
#> 3 3 [1,3] [1,25.8] [-12.5,12.5]
#> 4 4 (3,13] [1,25.8] [-12.5,12.5]
#> 5 5 (3,13] [1,25.8] [-12.5,12.5]
#> 6 6 (3,13] [1,25.8] [-12.5,12.5]
#> 7 7 (3,13] [1,25.8] [-12.5,12.5]
#> 8 8 (3,13] [1,25.8] [-12.5,12.5]
#> 9 9 (3,13] [1,25.8] [-12.5,12.5]
#> 10 10 (3,13] [1,25.8] [-12.5,12.5]
#> # ... with 255 more rows
summary(skewed_tbl$counts)
#> Min. 1st Qu. Median Mean 3rd Qu. Max.
#> 1.00 3.00 13.00 25.75 42.00 100.00
# Histogram showing skew
skewed_tbl %>%
ggplot(aes(counts)) +
geom_histogram(bins = 30)
# cut_number() evenly distributes observations into bins by quantile
skewed_tbl %>%
ggplot(aes(counts_cut_number)) +
geom_bar()
# cut_interval() evenly splits the interval across the range
skewed_tbl %>%
ggplot(aes(counts_cut_interval)) +
geom_bar()
# cut_width() uses the width = 25 to create bins that are 25 in width
skewed_tbl %>%
ggplot(aes(counts_cut_width)) +
geom_bar()
2018-11-01に reprexパッケージ (v0.2.1)によって作成されました
追加のパッケージなしで、3はグループの数です:
> findInterval(das$wt, unique(quantile(das$wt, seq(0, 1, length.out = 3 + 1))), rightmost.closed = TRUE)
[1] 1 1 1 2 2 2 3 1 3 3 3 2 1 3 2
関心のある値の代表的なサンプルを使用して、変位値の計算を高速化できます。 FindInterval
関数のドキュメントを再確認してください。