【问题标题】:Categorize numeric variable into group/ bins/ breaks将数值变量分类为组/箱/中断
【发布时间】:2021-08-13 14:21:06
【问题描述】:

我正在尝试将数字变量(年龄)分类为由间隔定义的组,因此它不会是连续的。我有这个代码:

data$agegrp(data$age >= 40 & data$age <= 49) <- 3
data$agegrp(data$age >= 30 & data$age <= 39) <- 2
data$agegrp(data$age >= 20 & data$age <= 29) <- 1

上面的代码在生存包下不起作用。它给了我:

invalid function in complex assignment

你能指出错误在哪里吗? data 是我正在使用的数据框。

【问题讨论】:

  • 使用[ 进行子集化,而不是(
  • 您要使用的函数是cut
  • @joan 你能告诉我它是如何使用 cut 完成的吗?
  • 答案取决于你想要什么结果? a) 只是一个整数(或 NA)b) 因子标签或确实 c) 二分/虚拟变量数组? findInterval() 只能做第一个,而 cut() 两者都做。 findInterval() 更快(O(log(no. of bins)),尽管这很少成为问题。

标签: r binning categorization bins


【解决方案1】:

我们可以使用dplyr:

library(dplyr)

data <- data %>% mutate(agegroup = case_when(age >= 40  & age <= 49 ~ '3',
                                             age >= 30  & age <= 39 ~ '2',
                                             age >= 20  & age <= 29 ~ '1')) # end function

与其他方法相比,dplyr 更易于编写和解释。

【讨论】:

  • 您也可以在mutate 中使用cut 代替case_when。例如。 data %&gt;% mutate(agegroup = cut(ages, breaks = c(20, 30, 40, 50), right = T, labels = F))
  • @stlba 这是 /such/ 一个很好的答案,非常感谢。 labels=TRUE 甚至会给出合理的标签。
【解决方案2】:
myData$age_grp <- myData$age
myData$age_grp <- ifelse((myData$age>=10 & myData$age<=18) , 'minnor',myData$age_grp)
myData$age_grp <- ifelse((myData$age>18 & myData$age<=21) , 'junior',myData$age_grp)
myData$age_grp <- ifelse((myData$age>21 & myData$age<=25) , 'major_1',myData$age_grp)
myData$age_grp <- ifelse((myData$age>25 & myData$age<=30) , 'major_2',myData$age_grp)
myData$age_grp <- ifelse((myData$age>30 & myData$age<=40) , 'major_3',myData$age_grp)
myData$age_grp <- ifelse((myData$age>40 & myData$age<=55) , 'major_4',myData$age_grp)
myData$age_grp <- ifelse((myData$age>55) , 'minnor',myData$age_grp)
myData$age_grp<-as.factor(myData$age_grp)
summary(myData$age_grp)
library(dplyr)
myData <- select(myData, -(age) )

【讨论】:

    【解决方案3】:

    假设您的年龄存储在标记为age 的数据框列中。您的数据框是 df,并且您想要一个新列 age_grouping,其中包含您的年龄所在的“桶”。

    在此示例中,假设您的年龄范围为 0 -> 100,并且您希望每 10 年对他们进行一次分组。以下代码将通过将这些间隔存储在新的age grouping 列中来完成此操作:

    df$age_grouping <- cut(df$age, c(0:100, 10))
    

    【讨论】:

    • 你的意思是cut(df$age, seq(0, 100, 10))
    【解决方案4】:

    我会在这里使用findInterval()

    首先,补一些样本数据

    set.seed(1)
    ages <- floor(runif(20, min = 20, max = 50))
    ages
    # [1] 27 31 37 47 26 46 48 39 38 21 26 25 40 31 43 34 41 49 31 43
    

    使用findInterval() 对您的“年龄”向量进行分类。

    findInterval(ages, c(20, 30, 40))
    # [1] 1 2 2 3 1 3 3 2 2 1 1 1 3 2 3 2 3 3 2 3
    

    或者,按照 cmets 中的建议,cut() 在这里也很有用:

    cut(ages, breaks=c(20, 30, 40, 50), right = FALSE)
    cut(ages, breaks=c(20, 30, 40, 50), right = FALSE, labels = FALSE)
    

    【讨论】:

    • @leian,你试过代码了吗?它应该。但是,当在 SO 的 R 标签中提问时,如果您需要更有针对性的帮助,最好包含一个最小的reproducible example
    • 但是这个 findInterval() 结果的变量名是什么?
    • 随心所欲!从你的例子中,我假设你会做类似data$agegrp &lt;- findInterval(data$age, c(20, 30, 40))
    【解决方案5】:

    此答案提供了两种使用data.table 包解决问题的方法,这将大大提高处理速度。如果要处理大型数据集,这一点至关重要。

    1s Approach:对先前答案的改编,但现在使用data.table + 包括labels

    library(data.table)
    
    agebreaks <- c(0,1,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,500)
    agelabels <- c("0-1","1-4","5-9","10-14","15-19","20-24","25-29","30-34",
                   "35-39","40-44","45-49","50-54","55-59","60-64","65-69",
                   "70-74","75-79","80-84","85+")
    
    setDT(data)[ , agegroups := cut(age, 
                                    breaks = agebreaks, 
                                    right = FALSE, 
                                    labels = agelabels)]
    

    第二种方法:这是一种更冗长的方法,但它也更清楚地说明了每个年龄段的确切内容:

    setDT(data)[age <1, agegroup := "0-1"]
    data[age >0 & age <5, agegroup := "1-4"]
    data[age >4 & age <10, agegroup := "5-9"]
    data[age >9 & age <15, agegroup := "10-14"]
    data[age >14 & age <20, agegroup := "15-19"]
    data[age >19 & age <25, agegroup := "20-24"]
    data[age >24 & age <30, agegroup := "25-29"]
    data[age >29 & age <35, agegroup := "30-34"]
    data[age >34 & age <40, agegroup := "35-39"]
    data[age >39 & age <45, agegroup := "40-44"]
    data[age >44 & age <50, agegroup := "45-49"]
    data[age >49 & age <55, agegroup := "50-54"]
    data[age >54 & age <60, agegroup := "55-59"]
    data[age >59 & age <65, agegroup := "60-64"]
    data[age >64 & age <70, agegroup := "65-69"]
    data[age >69 & age <75, agegroup := "70-74"]
    data[age >74 & age <80, agegroup := "75-79"]
    data[age >79 & age <85, agegroup := "80-84"]
    data[age >84, agegroup := "85+"]
    

    虽然这两种方法应该给出相同的结果,但出于两个原因,我更喜欢第一种。 (a) 写起来更短,(2) 年龄组以正确的方式排序,这对于可视化数据至关重要。

    【讨论】:

    • 第二种方法似乎不适用于 R 3.2。它给出了一个错误找不到函数“:=”
    • 它对我有用。确保加载 data.tablelibrary(data.table) ;并且您正在使用 data.table (不是数据框)setDT(your_dataframe) # convert your DF into a data.table
    猜你喜欢
    • 2022-01-06
    • 1970-01-01
    • 1970-01-01
    • 2014-10-04
    • 2011-01-31
    • 2021-02-28
    相关资源
    最近更新 更多