根据百分位分配标签

时间:2018-02-17 21:27:16

标签: r percentile

尝试将Python问题解决为R代码。

我想根据新专栏中的成绩分配标题。

例如:

  • ' A'对于大于或等于99.92 th 百分位数的值
  • ' B'值小于99.92 th 百分位数但大于或等于84.92 th 百分位数
  • ' C'值小于84.92 th 百分位数但大于或等于59.92 th 百分位数
  • ' d'值小于59.92 th 百分位数但大于或等于29.92 th 百分位数
  • ' E'对于小于29.92 th 百分位数但大于或等于15.92 th 百分位数的值
  • ' F'对于低于15.92 th 百分位数的所有值。

有这一栏:

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

这就是我的尝试。

rlang::syms

依旧......但是在第一次之后我认为在下一个百分位数应该有一个减法,因为较低的百分位数不应该包含更高的百分位数。这就是我得到它的方式。

2 个答案:

答案 0 :(得分:2)

概述

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

可重复的示例

我使用read.table()函数将您的示例数据导入

然后,我将quantiles()的输出中的样本分位数存储在interested.quantiles中。每个百分位数 - probs参数中每个[0,1]值一个 - 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 th 。如果为true,则返回' A&#39 ;;如果为false,则继续检查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。以下是应用于新数据集的相同逻辑。

注意:没有&#39; F&#39; df$Label中的值。这不是一个错误;相反,这是理解数据的一个很好的教训。 df$rfm_score中20.77%的值是1.8。感兴趣的最小百分位是15.92% - 毫不奇怪 - 与1.8的值相关联。当sapply()中的匿名函数搜索小于1.8的值时,它将显示为空。因此,没有df$rm_score可以拥有标签&#39; F&#39;因为该向量中的值不小于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 #

答案 1 :(得分:0)

问:

  

A列的前0.8%   B为下一个15%的列   C为下一个25%的列   D为下一个30%的列   E为下一个14%的列   F为列的其余部分

削减:

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