【问题标题】:lump factor based on another column基于另一列的综合因子
【发布时间】:2018-10-04 14:53:51
【问题描述】:

该示例显示了不同工厂的生产输出的测量值, 其中第一列表示工厂 最后一列是生产量。

factory <- c("A","A","B","B","B","B","B","C","D")
production <- c(15, 2, 1, 1, 2, 1, 2,20,5)
df <- data.frame(factory, production)
df
  factory production
1       A         15
2       A          2
3       B          1
4       B          1
5       B          2
6       B          1
7       B          2
8       C         20
9       D          5

现在我想根据数据集中的总产量将工厂归为更少的级别。

使用普通的 forcats::fct_lump,我可以按你出现的行数来汇总它们,例如制作 3 个关卡:

library(tidyverse)    
df %>% mutate(factory=fct_lump(factory,2))
      factory production
    1       A         15
    2       A          2
    3       B          1
    4       B          1
    5       B          2
    6       B          1
    7       B          2
    8   Other         20
    9   Other          5

但我想根据总和(生产)对它们进行汇总,保留前 n=2 个工厂(按总产量)并将其余工厂汇总。期望的结果:

1       A         15
2       A          2
3   Other          1
4   Other          1
5   Other          2
6   Other          1
7   Other          2
8       C         20
9   Other          5

有什么建议吗?

谢谢!

【问题讨论】:

    标签: r tidyverse forcats


    【解决方案1】:

    这里的关键是应用特定的理念,以便根据生产总和将工厂组合在一起。请注意,这种理念与您在(真实)数据集中拥有的实际值有关。

    选项 1

    以下示例将总产量等于或小于 15 的工厂组合在一起。如果您想要另一个分组,您可以修改阈值(例如,使用 18 而不是 15)

    factory <- c("A","A","B","B","B","B","B","C","D")
    production <- c(15, 2, 1, 1, 2, 1, 2,20,5)
    df <- data.frame(factory, production, stringsAsFactors = F)
    
    library(dplyr)
    
    df %>%
      group_by(factory) %>%
      mutate(factory_new = ifelse(sum(production) > 15, factory, "Other")) %>%
      ungroup()
    
    # # A tibble: 9 x 3
    #   factory production factory_new
    #   <chr>        <dbl> <chr>      
    # 1 A               15 A          
    # 2 A                2 A          
    # 3 B                1 Other      
    # 4 B                1 Other      
    # 5 B                2 Other      
    # 6 B                1 Other      
    # 7 B                2 Other      
    # 8 C               20 C          
    # 9 D                5 Other 
    

    我正在创建 factory_new 而不删除(原始)factory 列。

    选项 2

    这是一个示例,您可以根据工厂的产量对工厂进行排名/排序,然后您可以选择一些顶级工厂保持原样并将其余工厂分组

    factory <- c("A","A","B","B","B","B","B","C","D")
    production <- c(15, 2, 1, 1, 2, 1, 2,20,5)
    df <- data.frame(factory, production, stringsAsFactors = F)
    
    library(dplyr)
    
    # get ranked factories based on sum production
    df %>%
      group_by(factory) %>%
      summarise(SumProd = sum(production)) %>%
      arrange(desc(SumProd)) %>%
      pull(factory) -> vec_top_factories
    
    # input how many top factories you want to keep
    # rest will be grouped together
    n = 2
    
    # apply the grouping based on n provided
    df %>%
      group_by(factory) %>%
      mutate(factory_new = ifelse(factory %in% vec_top_factories[1:n], factory, "Other")) %>%
      ungroup()
    
    # # A tibble: 9 x 3
    #   factory production factory_new
    #   <chr>        <dbl> <chr>      
    # 1 A               15 A          
    # 2 A                2 A          
    # 3 B                1 Other      
    # 4 B                1 Other      
    # 5 B                2 Other      
    # 6 B                1 Other      
    # 7 B                2 Other      
    # 8 C               20 C          
    # 9 D                5 Other 
    

    【讨论】:

    • 这是一个很好的步骤,但它仍然没有将前 n 条分开并将其余部分混为一谈。
    • 但这是您描述的理想输出。
    • 例如,是的。但是 forcats::fct_lump 接受参数 n 并保留前 n 级(按丰度)并将其余的合并为一个。也许我需要澄清一下。
    • 在上述解决方案中,哲学是更改sum(production) 阈值以获得不同的组。因此,您可以使用18 而不是15,您将获得不同的分组。如果您想提供n,我可以修改代码...
    【解决方案2】:

    只需指定权重参数w

    > df %>% 
    +   mutate(factory = fct_lump_n(factory, 2, w = production))
      factory production
    1       A         15
    2       A          2
    3   Other          1
    4   Other          1
    5   Other          2
    6   Other          1
    7   Other          2
    8       C         20
    9   Other          5
    

    注意:使用forcats::fct_lump_n,因为不再推荐通用的fct_lump

    【讨论】:

      【解决方案3】:

      我们也可以通过使用ave 创建一个逻辑条件来使用base R

      df$factory_new <- "Other"
      i1 <- with(df, ave(production, factory, FUN = sum) > 15)
      df$factory_new[i1] <- df$factory[i1]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-30
        • 2021-12-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多