【问题标题】:Add some grouping columns to a nested dataframe in R将一些分组列添加到 R 中的嵌套数据框
【发布时间】:2020-06-04 10:37:02
【问题描述】:

我在 R 中有一个包含 3 列(变量)的数据框。其中一个叫做 Region,是某种嵌套的。 我尝试复制其中的一小部分。

df <- data.frame (freq = c(70, 72, 74, 76, 78,
                           70, 72, 74, 76, 78,
                           70, 72, 74, 76, 78),
                  region = c('region.1','region.1','region.1','region.1', 'region.1',
                             'region.1.1','region.1.1','region.1.1', 'region.1.1', 'region.1.1',
                             'region.2','region.2', 'region.2', 'region.2', 'region.2'),
                  dBvalue = c(-30, -32, -42, -45, -47,
                              -33, -28, -22, -37, -35,
                              -36, -55, -43, -26, -49))

现在我想添加 3 个新列。 第一个是每个区域的观察计数(因此在这种情况下将是 1...5、1...5 等), 第二个必须包含一个分组值, ant last 应该有 Region 列的更高层次的聚合 在这种情况下,最终的 df 将是:

df <- data.frame (freq = c(70, 72, 74, 76, 78,
                           70, 72, 74, 76, 78,
                           70, 72, 74, 76, 78),
                  region = c('region.1','region.1','region.1','region.1', 'region.1',
                             'region.1.1','region.1.1','region.1.1', 'region.1.1', 'region.1.1',
                             'region.2','region.2', 'region.2', 'region.2', 'region.2'),
                  dBvalue = c(-30, -32, -42, -45, -47,
                              -33, -28, -22, -37, -35,
                              -36, -55, -43, -26, -49),
                  count = c(1,2,3,4,5,
                            1,2,3,4,5,
                            1,2,3,4,5),
                  group = c(1,1,1,1,1,
                            2,2,2,2,2,
                            3,3,3,3,3),
                  higher_region = c("region.1","region.1","region.1","region.1","region.1",
                  "region.1","region.1","region.1","region.1","region.1",
                  "region.2","region.2","region.2","region.2","region.2"))

我正在尝试使用循环函数,但我快疯了。有人有解决方案吗?也许使用其他方法?

【问题讨论】:

    标签: r nested data-manipulation


    【解决方案1】:

    Base中,您可以使用matchunique 来查找aveseq_along 来获取计数 em> 和 strsplitpaste 以获得 higher_region

    df$group <- match(df$region, unique(df$region))
    #df$group <- unclass(factor(df$region)) #Alternative
    df$count <- ave(df$group, df$region, FUN=seq_along)
    df$higher_region <- sapply(strsplit(df$region, ".", TRUE),
     function(x) paste(x[1:2], collapse = "."))
    #df$higher_region <- sub("^([^.]+\\.[^.]*).*", "\\1", df$region) #Alternative
    df
    #   freq     region dBvalue count group higher_region
    #1    70   region.1     -30     1     1      region.1
    #2    72   region.1     -32     2     1      region.1
    #3    74   region.1     -42     3     1      region.1
    #4    76   region.1     -45     4     1      region.1
    #5    78   region.1     -47     5     1      region.1
    #6    70 region.1.1     -33     1     2      region.1
    #7    72 region.1.1     -28     2     2      region.1
    #8    74 region.1.1     -22     3     2      region.1
    #9    76 region.1.1     -37     4     2      region.1
    #10   78 region.1.1     -35     5     2      region.1
    #11   70   region.2     -36     1     3      region.2
    #12   72   region.2     -55     2     3      region.2
    #13   74   region.2     -43     3     3      region.2
    #14   76   region.2     -26     4     3      region.2
    #15   78   region.2     -49     5     3      region.2
    

    【讨论】:

    • 我更喜欢你的 groupcount 基础解决方案,而不是我的。但我的higher_region 基本解决方案更简单sub("(region\\.\\d+).*","\\1",df$region)
    【解决方案2】:

    附加选项。 dplyr 1.0.0

    library(tidyverse)
    
    df %>% 
      group_by(region) %>% 
      mutate(count = row_number(),
             group = cur_group_id(),
             higher_region = str_extract(region, "^[A-z]*\\.\\d+")) %>% 
      ungroup()
    

    【讨论】:

      【解决方案3】:

      基础 R 解决方案:

      within(df, {
          region_str <- as.character(region)
          higher_region <- ifelse(grepl("[.]\\d[.]", region_str),
                                  gsub("[.]\\d$", "", region_str), region_str)
          count <- ave(region_str, region_str, FUN = length)
          rm(region_str)
        }
      )
      

      【讨论】:

        【解决方案4】:

        基础 R 解决方案:

        df$count <- unlist(lapply(split(df,df$region), function(x) 1:nrow(x)))
        df$group <- unlist(lapply(1:length(unique(df$region)), function(x) rep(x, nrow(split(df,df$region)[[x]]))))
        df$higher_region <- sub("(region\\.\\d+).*","\\1",df$region)
        
        > df
           freq     region dBvalue count group higher_region
        1    70   region.1     -30     1     1      region.1
        2    72   region.1     -32     2     1      region.1
        3    74   region.1     -42     3     1      region.1
        4    76   region.1     -45     4     1      region.1
        5    78   region.1     -47     5     1      region.1
        6    70 region.1.1     -33     1     2      region.1
        7    72 region.1.1     -28     2     2      region.1
        8    74 region.1.1     -22     3     2      region.1
        9    76 region.1.1     -37     4     2      region.1
        10   78 region.1.1     -35     5     2      region.1
        11   70   region.2     -36     1     3      region.2
        12   72   region.2     -55     2     3      region.2
        13   74   region.2     -43     3     3      region.2
        14   76   region.2     -26     4     3      region.2
        15   78   region.2     -49     5     3      region.2
        

        【讨论】:

          【解决方案5】:

          建议使用“dplyr”进行分组和计数,以及使用“as.factor”将区域“重新编码”为“第二个必须包含分组值”(尽管这会将相同 信息为'region',可能我误解了你的说明。最后我们使用'gsub'从'region'中提取第一个数字

          df <- data.frame (freq = c(70, 72, 74, 76, 78,
                                     70, 72, 74, 76, 78,
                                     70, 72, 74, 76, 78),
                            region = c('region.1','region.1','region.1','region.1', 'region.1',
                                       'region.1.1','region.1.1','region.1.1', 'region.1.1', 'region.1.1',
                                       'region.2','region.2', 'region.2', 'region.2', 'region.2'),
                            dBvalue = c(-30, -32, -42, -45, -47,
                                        -33, -28, -22, -37, -35,
                                        -36, -55, -43, -26, -49))
          
          library(dplyr)
          df %>% 
            group_by(region) %>% 
            mutate(count = row_number()) %>% 
            ungroup() %>% 
            mutate(group = as.numeric(as.factor(region)),
                   higher_region = gsub("[a-z.]*([0-9]).*", "\\1", region)) %>% 
            as.data.frame()
          

          返回:

             freq     region dBvalue count group higher_region
          1    70   region.1     -30     1     1             1
          2    72   region.1     -32     2     1             1
          3    74   region.1     -42     3     1             1
          4    76   region.1     -45     4     1             1
          5    78   region.1     -47     5     1             1
          6    70 region.1.1     -33     1     2             1
          7    72 region.1.1     -28     2     2             1
          8    74 region.1.1     -22     3     2             1
          9    76 region.1.1     -37     4     2             1
          10   78 region.1.1     -35     5     2             1
          11   70   region.2     -36     1     3             2
          12   72   region.2     -55     2     3             2
          13   74   region.2     -43     3     3             2
          14   76   region.2     -26     4     3             2
          15   78   region.2     -49     5     3             2
          

          编辑:

          两位数的“更高地区”:

          library(dplyr)
          df %>% 
            group_by(region) %>% 
            mutate(count = row_number()) %>% 
            ungroup() %>% 
            mutate(group = as.numeric(as.factor(region)),
                   higher_region = gsub("(region.[0-9]+)\\.?.*", "\\1", region)) %>% 
            as.data.frame()
          
          
             freq     region dBvalue count group higher_region
          1    70   region.1     -30     1     1      region.1
          2    72   region.1     -32     2     1      region.1
          3    74   region.1     -42     3     1      region.1
          4    76   region.1     -45     4     1      region.1
          5    78   region.1     -47     5     1      region.1
          6    70 region.1.1     -33     1     2      region.1
          7    72 region.1.1     -28     2     2      region.1
          8    74 region.1.1     -22     3     2      region.1
          9    76 region.1.1     -37     4     2      region.1
          10   78 region.1.1     -35     5     2      region.1
          11   70   region.2     -36     1     3      region.2
          12   72   region.2     -55     2     3      region.2
          13   74   region.2     -43     3     3      region.2
          14   76   region.2     -26     4     3      region.2
          15   78   region.2     -49     5     3      region.2
          

          【讨论】:

          • 它似乎可以工作,直到区域值在第一部分只有一个数字;例如,当我拥有区域 10.3 时,它会将其分配给 high_region 1 而不是 10
          • 如果我用不同的语法重命名区域值可能会更容易吗?例如:区域 1、区域 1_1、区域 1_2、...、区域 12_3?
          • 我仍然不确定我是否理解您想要 'higher_region' 的用途,但我在答案中添加了一个应该与 'region.11.1' 等一起使用的代码。
          • "higher_region" 应包含单词“region”、点和第一个数字。所以在区域值'region.12.1'的情况下,higher_region'将是region.12。现在我正在尝试您的解决方案,谢谢
          猜你喜欢
          • 1970-01-01
          • 2020-03-13
          • 1970-01-01
          • 2021-11-30
          • 2020-09-14
          • 1970-01-01
          • 2021-05-24
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多