根据百分位数分配标签

Assign Labels According to Percentiles

正在尝试将 Python 个问题转化为 R 代码。

我想在新栏目中根据成绩分配标题。

例如:

有这个专栏:

Grades
2.3
3
2
3.3
3.5
3.6
3.2
2.1
2.3
3.7
3.3
3.1
4.4
4.3
1.4
4.5
3.5

这是我试过的。

 quantile(w$Grades, c(.91, .75))

等等..但是在第一个之后,我认为应该在下一个百分位数上进行减法,因为较低的百分位数不应该包括 higher.This 我是这样得到的。

概述

我将分位数存储为向量,并使用 sapply() 中的这些值来标记 Grade 中落在分位数之间的值。

可重现的例子

我用的是read.table() function to import your example data into

之后,我存储了 quantiles() in interested.quantiles. Each percentile - one for each [0,1] value in the probs argument - represents the value below which a given percentage of observations in df$Grade fall 输出的样本分位数。

最后,我输入df$Grade作为sapply()中的X输入,并对X中的每个值应用匿名函数。该函数检查X的每个值属于六个组中的哪一个通过一系列 if() and else if() 功能。由于 interested.quantiles 中的值是按百分位数的降序创建的,if 语句检查 X 值是否大于或等于第 99.92。如果为真,则 returns 'A';如果为假,它将继续检查 X 在剩余百分位数中的位置。

# create data
df <-
  read.table( text = "Grades
2.3
3
2
3.3
3.5
3.6
3.2
2.1
2.3
3.7
3.3
3.1
4.4
4.3
1.4
4.5
3.5"
              , header = TRUE
  )


# create quantiles based on 
# interested probabilities
# from df$Grade
interested.quantiles <-
  quantile( x = df$Grades
            , probs = c( 0.9992, 0.8492, 0.5992, 0.2992, 0.1592 )
  )

# view vector
interested.quantiles
#  99.92%  84.92%  59.92%  29.92%  15.92% 
# 4.49872 4.05232 3.41744 2.85104 2.20944 

# Assign labels based on each
# Grade's value
df$Label <-
  sapply( X = df$Grades
          , FUN = function( i )
            if( i >= interested.quantiles[ 1 ] ){

              return( "A" )

            } else if( i < interested.quantiles[ 1 ] &&
                        i >= interested.quantiles[ 2 ] ){

              return( "B" )

            } else if( i < interested.quantiles[ 2 ] &&
                        i >= interested.quantiles[ 3 ] ){

              return( "C" )

            } else if( i < interested.quantiles[ 3 ] &&
                        i >= interested.quantiles[ 4 ] ){

              return( "D" )

            } else if( i < interested.quantiles[ 4 ] &&
                        i >= interested.quantiles[ 5 ] ){

              return( "E" )

            } else{

              return( "F")
            }

  )

# view results
df
#    Grades Label
# 1     2.3     E
# 2     3.0     D
# 3     2.0     F
# 4     3.3     D
# 5     3.5     C
# 6     3.6     C
# 7     3.2     D
# 8     2.1     F
# 9     2.3     E
# 10    3.7     C
# 11    3.3     D
# 12    3.1     D
# 13    4.4     B
# 14    4.3     B
# 15    1.4     F
# 16    4.5     A
# 17    3.5     C

# end of script #

附加数据集

在评论中给出了link to a CSV file of their actual data set。这是应用于新数据集的相同逻辑。

注意:df$Label 中没有 'F' 个值。这不是错误;相反,这是理解数据的重要一课。 df$rfm_score 中 20.77% 的值是 1.8。最小的兴趣百分位是 15.92%——这并不奇怪——与值 1.8 相关。当 sapply() 中的匿名函数搜索小于 1.8 的值时,结果为空。因此,没有 df$rm_score 可以拥有标签 'F',因为该向量中没有任何值小于 1.8。

# create data
df <- 
  read.csv( file = "http://download1519.mediafire.com/cjsv2c7r112g/3n6c5e6q2wdemmn/stackoverfl"
            , header = TRUE
            , stringsAsFactors = FALSE
  )

# view data
str( df )
# 'data.frame': 157711 obs. of  13 variables:
# $ X              : int  9 128 193 227 265 291 311 419 422 434 ...
# $ Member_id      : int  100010 100259 100378 100443 100535 100588 100619 100811 100816 100833 ...
# $ Invoice_id     : int  1728650 1613593 1617369 1597363 1733884 1598267 1603355 1619466 1688050 1645517 ...
# $ Grandtotal     : num  9.9 2.5 25.8 32.1 10.3 ...
# $ InvoiceDate    : chr  "2017-03-18" "2017-01-10" "2017-01-12" "2017-01-04" ...
# $ recency        : int  65 44 70 1 11 40 58 15 81 22 ...
# $ freq           : int  7 10 7 11 9 7 13 10 9 9 ...
# $ monetary_v     : num  95.3 114.5 103.6 144.4 113.3 ...
# $ rank_recency   : int  3 3 3 3 3 3 3 3 3 3 ...
# $ rank_freq      : int  5 5 5 5 5 5 5 5 5 5 ...
# $ rank_monetary_v: int  5 5 5 5 5 5 5 5 5 5 ...
# $ rfm_cell       : int  355 355 355 355 355 355 355 355 355 355 ...
# $ rfm_score      : num  4.6 4.6 4.6 4.6 4.6 4.6 4.6 4.6 4.6 4.6 ...

# View the range of values first
table( df$rfm_score )
#   1.8   2.1   2.3   2.4   2.6   2.7   2.9     3   3.1   3.2   3.3 
# 32764 17649 10107  1633 23781   371  7725   198 11670  4251   177 
#  3.4   3.5   3.6   3.7   3.8   3.9     4   4.1   4.2   4.3   4.4 
# 8360  3051   256  6108  2537   724  5614  2484  4580  5621  4002 
#  4.6 
# 4048 

# create quantiles based on 
# interested probabilities
# from df$rfm_score
interested.quantiles <-
  quantile( x = df$rfm_score
            , probs = c( 0.9992, 0.8492, 0.5992, 0.2992, 0.1592 )
  )

# view vector
interested.quantiles
# 99.92% 84.92% 59.92% 29.92% 15.92% 
#    4.6    4.0    3.1    2.1    1.8 


# Assign labels based on each
# row's df$rfm_score
df$Label <-
  sapply( X = df$rfm_score
          , FUN = function( i )
            if( i >= interested.quantiles[ 1 ] ){

              return( "A" )

            } else if( i < interested.quantiles[ 1 ] &&
                       i >= interested.quantiles[ 2 ] ){

              return( "B" )

            } else if( i < interested.quantiles[ 2 ] &&
                       i >= interested.quantiles[ 3 ] ){

              return( "C" )

            } else if( i < interested.quantiles[ 3 ] &&
                       i >= interested.quantiles[ 4 ] ){

              return( "D" )

            } else if( i < interested.quantiles[ 4 ] &&
                       i >= interested.quantiles[ 5 ] ){

              return( "E" )

            } else if( i < interested.quantiles[ 5 ] ){

              return( "F")
            }
  )

# view the results
table( df$Label, useNA = "ifany" )
#    A     B     C     D     E 
# 4048 22301 37134 61464 32764 

# Wait..why aren't there any F values?
length( which( df$rfm_score < interested.quantiles[ 5 ] ) ) # [1] 0

# no "F" values are given because the
# there are not any values less than
# the 5th element in interested.quantiles

# end of script #

问:

A for the top 0.8% of the column B for next 15% of the column C for next 25% of the column D for next 30% of the column E for next 14% of the column F for rest of the column

削减时间:

cuts <- c(1, 1 - cumsum( c(0.008, .15 ,.25,.30,.14)), 0)
cuts
[1] 1.000 0.992 0.842 0.592 0.292 0.152 0.000

需要颠倒字母顺序:

cut(dfrm$Grades, breaks= quantile(dfrm$Grades, cuts) ,include.lowest=TRUE, labels=LETTERS[6:1])
 [1] E D F D C C D F E C D D B B F A C
Levels: F E D C B A