R语言 合并一个变量具有相同值的所有后续行

falq053o  于 2023-04-03  发布在  其他
关注(0)|答案(4)|浏览(175)

我有一个data.frame,如下所示:

set.seed(123)
df <- data.frame(group = sample(c("a", "b", "c"), 20, replace = TRUE),
                 value = round(runif(20)*10))

# output
   group value
1      c    10
2      c     7
3      c     7
4      b     5
5      c     6
6      b     3
7      b     1
8      b    10
9      c     9
10     a     7
11     b     8
12     b     0
13     a     5
14     b     8
15     c     2
16     a     3
17     c     2
18     c     1
19     a     4
20     a     4

我想对所有具有相同group的行的value求和,但前提是这些行是后续的。预期输出为:

# output
   group values
1      c     24
2      b      5
3      c      6
4      b     14
5      c      9
6      a      7
7      b      8
8      a      5
9      b      8
10     c      2
11     a      3
12     c      3
13     a      8

我考虑过使用lag(),但是我需要知道一个组的出现频率。我该如何解决这个问题?

6rqinv9w

6rqinv9w1#

您可以使用dplyr::consecutive_iddata.table::rleid按连续值分组:
使用dplyr

library(dplyr)
df %>% 
  mutate(id = consecutive_id(group)) %>% 
  summarise(value = sum(value), .by = c(id, group)) %>% 
  select(-id)

data.table中:

library(data.table)
setDT(df)[, .(group = first(group), value = sum(value)), by = rleid(group)][, rleid := NULL][]

创建分组的第三个选项是使用lagcumsum

df %>% 
  mutate(id = cumsum(lag(group, default = "not a letter") != group))
imzjd6km

imzjd6km2#

使用rle的基本R选项

with(
  df,
  {
    x <- rle(group)
    x$lengths <- by(value, rep(seq_along(x$lengths), x$lengths), sum)
    setNames(rev(list2DF(x)), names(df))
  }
)

给予

group value
1      c    24
2      b     5
3      c     6
4      b    14
5      c     9
6      a     7
7      b     8
8      a     5
9      b     8
10     c     2
11     a     3
12     c     3
13     a     8
ct3nt3jp

ct3nt3jp3#

使用naked R I将创建一个新的列,检测组的变化,在此基础上进行分割,然后计算任何你想要的。

set.seed(123)
xy <- data.frame(group = sample(c("a", "b", "c"), 20, replace = TRUE),
                 value = round(runif(20)*10))

spl <- rle(xy$group)

xy$int_groups <- rep(1:length(spl$values), times = spl$lengths)

xy.split <- split(x = xy, f = xy$int_groups)

out <- lapply(X = xy.split, FUN = function(x) {
  data.frame(group = unique(x$group), values = sum(x$value))
})

do.call(rbind, out)

   group values
1      c     24
2      b      5
3      c      6
4      b     14
5      c      9
6      a      7
7      b      8
8      a      5
9      b      8
10     c      2
11     a      3
12     c      3
13     a      8
ne5o7dgx

ne5o7dgx4#

另一个 naked R 替代方案:

poor_rleid <- \(x) cumsum(x != c("", head(x, -1L)))
data.frame(
  group = rle(df$group)$values,
  value = split(df$value, poor_rleid(df$group)) |> sapply(sum)
)
)
#    group value
# 1      c    24
# 2      b     5
# 3      c     6
# 4      b    14
# 5      c     9
# 6      a     7
# 7      b     8
# 8      a     5
# 9      b     8
# 10     c     2
# 11     a     3
# 12     c     3
# 13     a     8

相关问题