【问题标题】:How to divide a table into different levels based on values in R? [duplicate]如何根据 R 中的值将表划分为不同的级别? [复制]
【发布时间】:2016-03-20 03:58:40
【问题描述】:

假设我有以下数据

ID  Category    Price   Month
1   X            2       1
1   X            2       2
1   X            2       3
1   X            2       4
2   X            3       1
2   X            3       2
2   X            3       3
2   X            3       4
3   X            1       1
3   X            1       2
3   X            1       3
3   X            1       4
4   X            10      1
4   X            10      2
4   X            10      3
4   X            10      4
5   Y            5       1
5   Y            5       2
5   Y            5       3
5   Y            5       4
6   Y            2       1
6   Y            2       2
6   Y            2       3
6   Y            2       4
7   Y            1       1
7   Y            1       2
7   Y            1       3
7   Y            1       4
8   Y            10      1
8   Y            10      2
8   Y            10      3
8   Y            10      4

特定类别的产品有不同的价格,有些是低价的,有些是高价的。我想要一个新变量“Price Level”来显示产品是低价产品、中价产品还是高价产品。

级别定义如下。 它采用特定类别中所有产品的价格并分为 4 个百分位。

  • 第 1 个百分位数 = 低
  • 第二和第三百分位数 = 中等
  • 第 4 个百分位数 = 高

所以表格看起来像这样

ID  Category    Price   Month   Price Level
1   X            4       1        Medium
1   X            4       2        Medium
1   X            4       3        Medium
1   X            4       4        Medium
2   X            3       1        Medium
2   X            3       2        Medium
2   X            3       3        Medium
2   X            3       4        Medium
3   X            1       1        Low
3   X            1       2        Low
3   X            1       3        Low
3   X            1       4        Low
4   X            10      1        High
4   X            10      2        High
4   X            10      3        High
4   X            10      4        High
5   Y            5       1        Medium
5   Y            5       2        Medium
5   Y            5       3        Medium
5   Y            5       4        Medium
6   Y            2       1        Low
6   Y            2       2        Low
6   Y            2       3        Low
6   Y            2       4        Low
7   Y            1       1        Low
7   Y            1       2        Low
7   Y            1       3        Low
7   Y            1       4        Low
8   Y            10      1        Low
8   Y            10      2        Low
8   Y            10      3        Low
8   Y            10      4        Low

【问题讨论】:

    标签: r


    【解决方案1】:

    您可以通过Category 跨data.frame split lapply,并在每个组上调用cutquantiledata.framedo.call(rbind, 将数据重新组合成单​​个 data.frame:

    do.call(rbind, lapply(split(df, df$Category), function(x){
        data.frame(x, Price_Level =  cut(x$Price, 
                                         quantile(x$Price, probs = c(0, .25, .75, 1)), 
                                         labels = c('Low', 'Medium', 'High'), 
                                         include.lowest = TRUE))
    }))
    
    #    ID Category Price Month Price_Level
    # 1   1        X     2     1      Medium
    # 2   1        X     2     2      Medium
    # 3   1        X     2     3      Medium
    # 4   1        X     2     4      Medium
    # 5   2        X     3     1      Medium
    # 6   2        X     3     2      Medium
    # 7   2        X     3     3      Medium
    # 8   2        X     3     4      Medium
    # 9   3        X     1     1         Low
    # 10  3        X     1     2         Low
    # 11  3        X     1     3         Low
    # 12  3        X     1     4         Low
    # 13  4        X    10     1        High
    # 14  4        X    10     2        High
    # 15  4        X    10     3        High
    # 16  4        X    10     4        High
    # 17  5        Y     5     1      Medium
    # 18  5        Y     5     2      Medium
    # 19  5        Y     5     3      Medium
    # 20  5        Y     5     4      Medium
    # 21  6        Y     2     1      Medium
    # 22  6        Y     2     2      Medium
    # 23  6        Y     2     3      Medium
    # 24  6        Y     2     4      Medium
    # 25  7        Y     1     1         Low
    # 26  7        Y     1     2         Low
    # 27  7        Y     1     3         Low
    # 28  7        Y     1     4         Low
    # 29  8        Y    10     1        High
    # 30  8        Y    10     2        High
    # 31  8        Y    10     3        High
    # 32  8        Y    10     4        High
    

    如果你只想返回单个列,但又不想担心分组搞乱你的订单,你可以使用等价的

    factor(ave(df$Price, df$Category, FUN = function(x){
        cut(x, 
            quantile(x, probs = c(0, .25, .75, 1)), 
            include.lowest = TRUE)
    }), levels = c(1, 2, 3), labels = c('Low', 'Medium', 'High'))
    

    带有dplyr的稍微不那么难看的版本:

    library(dplyr)
    df %>% group_by(Category) %>% mutate(Price_Level = cut(Price, 
                                                           quantile(Price, c(0, .25, .75, 1)), 
                                                           labels = c('Low', 'Medium', 'High'), 
                                                           include.lowest = TRUE))
    

    【讨论】:

    • 我尝试将代码应用于每个类别和月份中的行数不相等的原始数据,所以我收到错误“'breaks' is not unique”所以我尝试将分位数放在里面独特的功能,然后我得到错误“'breaks'和'labels'的长度不同”。如何解决?
    • 您能否使用导致问题的数据子集进行编辑?
    【解决方案2】:

    我们可以使用data.table

    library(data.table)
    setDT(df)[, Price_Level := cut(Price, 
                 quantile(Price, c(0, .25, .75, 1)), 
                labels = c('Low', 'Medium', 'High'),
                include.lowest = TRUE), by = Category]
    

    【讨论】:

    • 我尝试将代码应用于每个类别和月份中的行数不相等的原始数据,所以我收到错误“'breaks' is not unique”所以我尝试将分位数放在里面独特的功能,然后我得到错误“'breaks'和'labels'的长度不同”。如何解决?
    • @Jaykhan 在示例数据中,它正在工作。
    猜你喜欢
    • 2019-11-27
    • 2022-12-07
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    • 1970-01-01
    相关资源
    最近更新 更多