R:从数值变量和自定义/开放/单值间隔创建分类变量

Ber*_* U. 8 r intervals binning categorical-data dplyr

我经常发现自己试图从数值变量+用户提供的范围集创建分类变量.

例如,假设我有一个带有数字变量的data.frame,df$V并且想要创建一个新变量df$VCAT,以便:

  • df$VCAT= 0如果df$V等于0
  • df$VCAT= 1如果df$V介于0到10之间(即(0,10))
  • df$VCAT= 2 df$V等于10(即[10,10])
  • df$VCAT= 3是df$V10到20之间(即(10,20))
  • df$VCAT= 4 df$V大于或等于20(即[20,Inf])

我目前通过以下方式对自己的"评分函数"进行硬编码来做到这一点:

df = data.frame(V = seq(1,100))
df = df %>% mutate(VCAT = (V>0) + (V==10) + 2*(V>10) + (V>=20))
Run Code Online (Sandbox Code Playgroud)

我想知道在R中是否有更简单的hacky方法,最好使用dplyr(这样我可以链接命令).理想情况下,我正在寻找一个可以使用的短函数,mutate它将接收变量V和描述范围的向量,例如buckets.请注意,这里buckets可能没有以最佳方式描述,因为我不清楚如何允许用户自定义范围的端点.

sea*_*ean 1

对数字进行分类的一种方法是使用模运算符 删除余数%%。例如,以 20 为一组进行分组:

#create raw data
unbinned<-c(1.1,1.53,5,8.3,33.5,49.22,55,57.9,79.6,81,95,201,213)
rawdata<-as.data.frame(unbinned)

#bin the data into groups of 20
binneddata<-mutate(rawdata,binned=unbinned-unbinned %% 20)

#print the data
binneddata
Run Code Online (Sandbox Code Playgroud)

这会产生输出:

   unbinned binned
1      1.10      0
2      1.53      0
3      5.00      0
4      8.30      0
5     33.50     20
6     49.22     40
7     55.00     40
8     57.90     40
9     79.60     60
10    81.00     80
11    95.00     80
12   201.00    200
13   213.00    200
Run Code Online (Sandbox Code Playgroud)

所以 0 代表 0-<20,20 代表 20-<40、40 ,40-<60 等(当然,将值除以binned20 以获得像原始问题中那样的连续组)

奖金

如果你想通过将分箱值转换ggplot为字符串来使用分箱值作为分类变量,它们的顺序会很奇怪,例如200将出现在40之前,因为字母表中'2'出现在'4'之前,为了解决这个问题,使用该sprintf函数创建前导零。(3in%03d应该是您期望的最长数字的位数):

#convert the data into strings with leading zeros
binnedstring<-mutate(binneddata,bin_as_character=sprintf('%03d',binned))

#print the data
binnedstring
Run Code Online (Sandbox Code Playgroud)

给出输出:

   unbinned binned bin_as_character
1      1.10      0              000
2      1.53      0              000
3      5.00      0              000
4      8.30      0              000
5     33.50     20              020
etc.
Run Code Online (Sandbox Code Playgroud)

如果您想要000-<020,请使用算术创建上限并使用粘贴函数连接:

#make human readable bin value
binnedstringband<-mutate(
    binnedstring,
    nextband=binned+20,
    human_readable=paste(bin_as_character,'-<',sprintf('%03d',nextband),sep='')
)

#print the data
binnedstringband
Run Code Online (Sandbox Code Playgroud)

给予:

   unbinned binned bin_as_character nextband     human_readable
1      1.10      0              000       20           000-<020
2      1.53      0              000       20           000-<020
3      5.00      0              000       20           000-<020
4      8.30      0              000       20           000-<020
5     33.50     20              020       40           020-<040
etc.
Run Code Online (Sandbox Code Playgroud)