[英]R - cut2 - one bin for zeros and 10 for everything else
我有一個偏態分布的數據集,我想將其划分為具有相同觀察數量的箱 - 除了偏態。
澄清一下,我有大量的零,以及相對較少的 > 0 觀測值。
如果我使用 cut2 將值分為 10 個包括零的 bin,我會得到以下結果。
library(data.table)
library(Hmisc)
DT<-data.table(x=rep(0,100), y=rep(0,100))
DT<-rbind(DT, data.table(x=seq(1:100),y=seq(1:100)))
DT
x y
1: 0 0
2: 0 0
3: 0 0
4: 0 0
5: 0 0
---
196: 96 96
197: 97 97
198: 98 98
199: 99 99
200: 100 100
只看 x
data.table(DT[, cut2(x, g=10)])[,.N, by=V1]
V1 N
1: 0 100
2: [ 1, 21) 20
3: [21, 41) 20
4: [41, 61) 20
5: [61, 81) 20
6: [81,100] 20
因此,100 個零的存在已將 bin 移動到零以上的觀測值聚集成 5 個桶的點。
如果我專門過濾掉零並應用 10 個 bin,我會按預期得到以下結果...
data.table(DT[x>0, cut2(x, g=10)])[,.N, by=V1]
V1 N
1: [ 1, 11) 10
2: [11, 21) 10
3: [21, 31) 10
4: [31, 41) 10
5: [41, 51) 10
6: [51, 61) 10
7: [61, 71) 10
8: [71, 81) 10
9: [81, 91) 10
10: [91,100] 10
我想要做的是有 11 個桶 - 一個用於零,10 個用於非零。 我當然可以通過 2 個單獨的操作來應用它
DT[x==0, bin:=cut2(x, g=1)]
Warning message:
In min(diff(x.unique)) : no non-missing arguments to min; returning Inf
DT[x>0, bin:=cut2(x, g=10)]
DT[, .(min(x), max(x)), by=bin]
bin V1 V2
1: 0 0 0
2: [ 1, 11) 1 10
3: [11, 21) 11 20
4: [21, 31) 21 30
5: [31, 41) 31 40
6: [41, 51) 41 50
7: [51, 61) 51 60
8: [61, 71) 61 70
9: [71, 81) 71 80
10: [81, 91) 81 90
11: [91,100] 91 100
但是我必須為 y 重復那些相同的 2 個操作。 我的實際數據表大約有 30 列,所以我想知道是否有:
我可以看到的關鍵部分是過濾器部分 - 分布都偏向於零,但每列包含不同數量的觀測值,因此將具有不同的 bin。
任何指針將不勝感激。
大衛
ps 希望帖子的布局可以讓您剪切和粘貼代碼 - 為了清楚起見,我包含了輸出,但如果有問題,請告訴我。
編輯在查看@Eddi 的答案並應用於我的數據后,我可以看到我提供的數據與我實際運行的數據存在問題。
這些是在我的數據上使用 Eddi 的方法運行的結果(名稱被屏蔽)...
> data.table(XXX[, cut2(yyy, m =
sum(yyy > 0)/10)])[, .N, by = V1]
V1 N
1: [ 0, 4) 284
2: [3891,72337] 264
3: [1212, 3891) 264
4: [ 519, 1212) 264
5: [ 208, 519) 263
6: [ 49, 101) 267
7: [ 101, 208) 263
8: [ 11, 24) 258
9: [ 24, 49) 263
10: [ 4, 11) 252
> XXX[yyy==0, .N,]
[1] 74
> XXX[yyy>=0, .N,]
[1] 2642
我已經更新了測試數據集以重現這些結果,如下所示 - 主要是將潛在值的范圍擴展到 70,000 並隨機而不是順序生成它們。 還生成了 2700 個,而不是我正在使用的 100 個左右
DT<-data.table(x=rep(0,100), y=rep(0,100))
DT<-rbind(DT, data.table(x=runif(2600,1,70000),y=runif(2600,1,70000)))
DT
data.table(DT[, cut2(x, m = sum(x > 0)/10)])[, .N, by = V1]
V1 N
1: [ 0, 4798) 270
2: [41289,48407) 270
3: [11482,18413) 270
4: [48407,55678) 270
5: [55678,62157) 270
6: [33040,41289) 270
7: [25470,33040) 270
8: [ 4798,11482) 270
9: [62157,69983] 270
10: [18413,25470) 270
因此,這已將零桶卷入其余 10 個桶中 - 誠然,這不會對分布產生重大影響,但它是此方法似乎略有崩潰的列之一。
為測試數據中的錯誤道歉,我沒有預料到這種類型的影響。
歡迎任何有關如何進行的想法......
干杯
大衛
在收到 Eddi 的反饋和我自己對此的實驗后,我決定對列列表使用 for 循環,特別是首先對零進行分箱,然后分別對非零進行分箱。
DT<-data.table(x=rep(0,100), y=rep(0,100))
DT<-rbind(DT, data.table(x=runif(100,1,10000),y=runif(100,1,10000)))
DT
cols <- data.table(col_name=c("x","y"))
for(col in 1:nrow(cols)){
DT[get(cols[col, col_name])==0,(paste(cols[col,col_name],"_bin",sep="")):= cut2(get(cols[col, col_name]),g=1)]
DT[get(cols[col, col_name])>0,(paste(cols[col, col_name],"_bin",sep="")):= cut2(get(cols[col, col_name]),g=10)]
}
data.table(DT[, cut2(x, m = sum(x > 0)/10)])[, .N, by = V1]
V1 N
1: 0.00 100
2: [2540.22,4009.79) 10
3: [4923.05,5736.81) 10
4: [4009.79,4923.05) 10
5: [ 910.57,1563.99) 10
6: [5736.81,6121.23) 10
7: [ 9.77, 910.57) 10
8: [9240.77,9957.27] 10
9: [1563.99,2540.22) 10
10: [6121.23,7759.80) 10
11: [7759.80,9240.77) 10
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.