【问题标题】:compress / summarize string start and length data in R压缩/汇总R中的字符串开始和长度数据
【发布时间】:2019-12-10 22:44:29
【问题描述】:

我在一个较大的字符串中有一个data.frame 的(子)字符串位置。数据包含(子)字符串的开头及其长度。 (子)字符串的结束位置可以很容易地计算出来。

data1 <- data.frame(start = c(1,3,4,9,10,13),
                   length = c(2,1,3,1,2,1)
                   )

data1$end <- (data1$start + data1$length - 1)

data1
#>   start length end
#> 1     1      2   2
#> 2     3      1   3
#> 3     4      3   6
#> 4     9      1   9
#> 5    10      2  11
#> 6    13      1  13

由reprex package (v0.3.0) 于 2019 年 12 月 10 日创建

我想通过汇总连续(子)字符串(相互连接的字符串)来“压缩”这个data.frame,以便我的新数据如下所示:

data2 <- data.frame(start = c(1,9,13),
                   length = c(6,3,1)
                   )

data2$end <- (data2$start + data2$length - 1)

data2
#>   start length end
#> 1     1      6   6
#> 2     9      3  11
#> 3    13      1  13

由reprex package (v0.3.0) 于 2019 年 12 月 10 日创建

最好有一个基本的 R 解决方案可以让我从data1 到data2?

【问题讨论】:

  • data2 中不是 9-13 而不是 9-3 吗?
  • 数据对我来说似乎是正确的。
  • @akrun 比方说,这是实际数据:(1,2), (3), (4,5,6), (9), (10,11), (13)希望这会有所帮助。

标签: r string dataframe group-summaries


【解决方案1】:
f = cumsum(with(data1, c(0, start[-1] - head(end, -1))) != 1)
do.call(rbind, lapply(split(data1, f), function(x){
    with(x, data.frame(start = start[1],
                       length = tail(end, 1) - start[1] + 1,
                       end = tail(end, 1)))}))
#  start length end
#1     1      6   6
#2     9      3  11
#3    13      1  13

【讨论】:

  • 感谢您的回答。我特别喜欢do.call(rbind, lapply(split...) 的第二部分,作为处理基本 R 中类似问题的一种方式。但是,f 对我来说更容易理解 akrun 和 M 的方式——在下面将其定义为:f = with(data1, cumsum(start != c(0, end[-length(end)]) + 1))。也许您可以将其作为替代方案提及。
【解决方案2】:

使用dplyr,我们可以做到以下几点:

library(dplyr)

data1 %>% 
  group_by(consecutive = cumsum(start != lag(end, default = 0) + 1)) %>% 
  summarise(start = min(start), length=sum(length), end=max(end)) %>% 
  ungroup %>% select(-consecutive)

#> # A tibble: 3 x 3
#>   start length   end
#>   <dbl>  <dbl> <dbl>
#> 1     1      6     6
#> 2     9      3    11
#> 3    13      1    13

【讨论】:

  • 谢谢,这是一个非常简洁的方法!我想知道我们如何在基础 R 中做到这一点。
  • @M-- 使用 base R,它将是 transform(data1,consecutive = cumsum(start != c(0, end[-length(end)]) + 1))) 并在 aggregate 中使用它
  • 或bydo.call(rbind, by(df1, df1$consecutive, FUN = function(x) cbind(start = min(x$start), length = sum(x$length), end = max(x$end))))
  • @TimTeaFan 请发布另一个答案,而不是编辑它。干杯。
  • @M--抱歉,不知道不包括 akrun 的基本 R 方法是故意的(认为这会让其他读者更容易在一个答案中看到这两种方法)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多