按类别计算并相应地定义 class 名称

Calculate per category and define class name accordingly

数据是这样的:

temp <- data.frame(type = c("a","b","c","d"), value=runif(100, 10, 2380))
temp <- as.data.table(temp)

# type      value   
# 1:    a 2250.33013   
# 2:    b 1271.71251  
# 3:    c 2299.45486   
# 4:    d  807.30089  
# 5:    a   31.32157  

我想计算每个类型的四分位数,然后将 class 定义为每个分区的 class1,2,3,4。

我的目标是在不同类型之间平均分配 class 值。

我的第一个快速方法是这样的,

a <- temp[type == "a"]
b <- temp[type == "b"]
c <- temp[type == "c"]
d <- temp[type == "d"]

quantile(a$value)
quantile(b$value)
quantile(c$value)
quantile(d$value)

dt <- temp[, quantile := quantile(value), by = type]

然后创建dt$class <- ifelse(...)

但这似乎是解决这个问题的一种迂回方式。我觉得我可以在这里使用各种应用技术,但还没有找到相关主题。

我理想的结果应该是这样的(忽略这个数字)

# type      value   quantile            class
# 1:    a 2250.33013   31.32157         class1
# 2:    b 1271.71251  112.83298         class2
# 3:    c 2299.45486   33.67312         class3
# 4:    d  807.30089   40.06302         class4
# 5:    a   31.32157  535.78510         class1
# 6:    b  815.11432  808.63388         class2
# 7:    c 1341.02811 1128.15997         class3
# 8:    d  964.20982  650.42241         class4
# 9:    a 2208.44555 1290.29102         class1
# 10:    b 1167.64278 1369.88565        class2
# 11:    c  349.35402 1526.66226        class3
# 12:    d  643.73551 1073.49396        class4

因此,最终我会在整个类型中均匀分布 classes。请与我分享您以更聪明的方式做到这一点的想法。谢谢!

要实现您想要的效果,您可以使用 cut 函数,如下所示:

temp[, quant := quantile(value), by = type
     ][, clas := cut(value, 
                     unique(quant), 
                     labels = paste0('class',1:4), 
                     include.lowest = TRUE), 
       by = type]

这给你:

> temp
     type      value      quant   clas
  1:    a 2078.94314  129.56675 class4
  2:    b 1360.65024  107.40551 class2
  3:    c 1753.82409   91.92594 class4
  4:    d 1384.85250  149.01646 class4
  5:    a  653.64766  456.96086 class2
  6:    b 1925.33187  565.15271 class4
....
 95:    c 1460.56660 1676.58185 class3
 96:    d  673.59436 1314.27001 class2
 97:    a 1147.94976 2203.73669 class3
 98:    b  648.93761 2317.71071 class2
 99:    c 1341.69222 2328.16911 class2
100:    d  149.01646 2268.54346 class1

如果您只对 clas 变量感兴趣,您还可以:

temp[, clas := cut(value, 
                   quantile(value), 
                   labels = paste0('class',1:4), 
                   include.lowest = TRUE), 
     by = type]

附带说明:当使用随机值生成器(如 samplerunifrnorm)提供样本数据时,最好使用 set.seed()。此外:最好不要让变量与函数同名(因此在我的回答中使用 quantclas)。

使用数据:

set.seed(26042017)
temp <- data.table(type = c("a","b","c","d"), value = runif(100, 10, 2380))

您可以使用 dplyr 按类型分组,然后使用 ntile 在组内排名。无需将 temp 转换为数据 table.

library(dplyr)
temp <- data.frame(type = c("a","b","c","d"),
                   value=runif(100, 10, 2380))
temp %>% 
  group_by(type) %>% 
  mutate(class = ntile(value, 4)) %>% 
  ungroup()

# A tibble: 100 × 3
     type     value class
   <fctr>     <dbl> <int>
1       a  347.7757     1
2       b  789.0118     2
3       c  952.6286     2
4       d  826.3092     1
5       a  378.6079     1
6       b  136.0738     1
7       c 1742.9738     4
8       d 1788.1156     3
9       a 1133.6740     3
10      b 2283.8092     4
# ... with 90 more rows