繁体   English   中英

将一些分组列添加到 R 中的嵌套 dataframe

[英]Add some grouping columns to a nested dataframe in R

我在 R 中有一个带有 3 列(变量)的 dataframe。 其中一个叫做 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 最后一个应该具有更高的层次结构级别在这种情况下,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"))

我正在尝试使用循环功能,但我快疯了。 有人有解决方案吗? 也许使用替代方法?

Base中,您可以使用matchunique来查找groupaveseq_along来获取计数,而strsplitpaste来获取更高的区域。

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

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

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

附加选项。 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()

基础 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)
  }
)

基础 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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM