从因子变量的区间获取端点

Obtain endpoints from interval that is factor variable

设置 我从以下正态混合模型中抽取 1,000,000 个观测值,然后对这些观测值进行分类,使得每个 10,000 个分类箱都具有相同数量的观测值(即 100)。这会以 (a,b] 的形式为每个 bin 创建一个因子,其中 ab 是数字。

#Random sample
set.seed(1234)
X = ks::rnorm.mixt(n=1000000,mus=c(0.2,0.8),sigmas=c(0.04,0.01),props=c(0.95,0.05))

#Bins based on random sample with ~100 observations in each bins
bins = ggplot2::cut_number(X,10000)

dat = data.frame(X,bins)

问题 我想从因子 (a,b] 中提取数字 ab。这是垃圾箱的样子:

> head(table(bins))
bins
[0.00501617,0.0518875]  (0.0518875,0.0594831]  (0.0594831,0.0640679] 
                   100                    100                    100 
 (0.0640679,0.0670062]  (0.0670062,0.0694194]  (0.0694194,0.0717924] 
                   100                    100                    100 
> tail(table(bins),20)
bins
(0.817766,0.818032]   (0.818032,0.8183]   (0.8183,0.818544] (0.818544,0.818879] 
                100                 100                 100                 100 
(0.818879,0.819112] (0.819112,0.819394] (0.819394,0.819664] (0.819664,0.819979] 
                100                 100                 100                 100 
(0.819979,0.820328] (0.820328,0.820727] (0.820727,0.821118]  (0.821118,0.82158] 
                100                 100                 100                 100 
 (0.82158,0.822109] (0.822109,0.822646] (0.822646,0.823253]  (0.823253,0.82408] 
                100                 100                 100                 100 
 (0.82408,0.825026] (0.825026,0.826417] (0.826417,0.828651]  (0.828651,0.84424] 
                100                 100                 100                 100 

如您所见,因数中的数字并不总是具有相同的位数,它们前面可能有 0(例如 (0.0518875,0.0594831])。

我最初尝试使用

仅提取数字部分
endpts=na.omit(as.numeric(unlist(strsplit(as.character(unlist(bins)),"[^0-9]+"))))

对于上面的bin((0.0518875,0.0594831]),这个程序会输出 518875 594831,但由于尾随零消失,它可以映射到多个值(例如 0.518875 0.594831)。此外,有些 bin 中的一个或两个数字具有不同的位数(例如 (0.818032,0.8183])。在尝试获取端点时,输出中缺乏一致性给我带来了问题。最终,我想获得左右端点。有什么建议吗?

EDIT 我还查看了 ggplot2::cut_number 的代码,它使用了 cut 函数。 cut 中默认输入的位数是 dig.lab=3,但这似乎没有反映在上面的输出中。

我认为你可以利用结构(a, b]。我没有尝试使用真实数据,但这是我的尝试:

s <- c("(0.0518875,0.0594831]", "0.818032,0.8183]")
lapply(strsplit(s, ","), function(x) gsub("\(|]", "", x))

[[1]]
[1] "0.0518875" "0.0594831" 

[[2]]
[1] "0.818032" "0.8183" 

需要号码的可以按as.numeric改成号码

这种经过简单测试的方法的一些东西:

unique( as.numeric(  unlist( 
                 strsplit( gsub( "[][(]" , "", levels(bins)[1:5] ) , ","))))

我学会了"read nested R code from the inside-out"。第一个 (1) 使用字符 class 模式删除侧翼“(”、“[”和“]”,然后 (2) 以逗号分隔,(3) "vectorizes" 列表结构 unlist, (4) 然后转换为数字,最后 (5) 删除重复项。这表明它使用换行符进行格式化:

unique(                    #     (5)
  as.numeric(                  #     (4)
      unlist(                        #     (3)
            strsplit(                     #     (2)
                gsub( "[][(]" , "", levels(bins)[1:5] ) , ",") # (1)
       )))

这已在您的示例中进行了测试,并为使用前 5 个级别的较小示例生成了此示例:

unique( as.numeric(  unlist( strsplit( gsub( "[][(]" , "", levels(bins)[1:5] ) , ","))))
[1] 0.00501617 0.05188750 0.05948310 0.06406790 0.06700620 0.06941940

我将 "vectorizes" 这个词放在引号中,因为它并不是 R 术语中那个词的真正含义,它指的是 return 一个等长向量作为其输入的操作。

这是我的建议的结果,即在项目 not 中保留小数点(句点)用作拆分标准,并与我的代码将交付的内容相匹配。您不清楚是只想要唯一值还是每个项目的值:

endpts= na.omit( as.numeric( unlist( strsplit( as.character( unlist(bins)),"[^0-9.]+"))))

 head(endpts)
#[1] 0.216698 0.216709 0.243665 0.243682 0.201100 0.201114
 end2 <- unique( as.numeric(  unlist( strsplit( gsub( "[][(]" , "", levels(bins) ) , ","))))
head(end2)
#[1] 0.00501617 0.05188750 0.05948310 0.06406790 0.06700620 0.06941940
 length(endpts)
#[1] 2000000
 length(end2)
#[1] 10001