重建/扩展先前在每个组ID内的子组ID上折叠的data.frame

重建/扩展先前在每个组ID内的子组ID上折叠的data.frame,r,dataframe,R,Dataframe,这个问题是问你如何“重建”一个数据框,该数据框以前是基于段id折叠的,包含开始变量和结束变量,并放入一个表中,该表在每个间隔内扩展到每个元素 考虑以下示例数据集: my_df <- structure(list(group_id = c(1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 6, 6, 6, 7, 7, 7, 8, 9), start = c(1L, 1

这个问题是问你如何“重建”一个数据框,该数据框以前是基于段id折叠的,包含开始变量和结束变量,并放入一个表中,该表在每个间隔内扩展到每个元素

考虑以下示例数据集:

my_df <- structure(list(group_id = c(1, 2, 2, 2, 3, 
                            3, 3, 4, 4, 5, 6, 6, 6, 
                            7, 7, 7, 8, 9), start = c(1L, 1L, 13L, 24L, 1L, 16L, 30L, 1L, 14L, 1L, 1L, 6L, 11L, 1L, 9L, 20L, 
                                                                                 1L, 1L), end = c(22L, 13L, 24L, 27L, 16L, 30L, 51L, 14L, 
                                                                                                      26L, 8L, 6L, 11L, 17L, 9L, 20L, 26L, 17L, 14L), segment_id = c(1L, 
                                                                                                                                                                     1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 1L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 
                                                                                                                                                                     1L)), row.names = 3377225:3377242, class = "data.frame", .Names = c("group_id", 
                                                                                                                                                                                                                                         "start", "end", "segment_id"))
我找到的唯一解决方案是转换矩阵中的data.frame并在所有段上执行循环

要澄清,请毫不犹豫地询问。

my\u df%
my_df <- structure(list(group_id = c(1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 6, 6, 6, 7, 7, 7, 8, 9), 
start = c(1L, 1L, 13L, 24L, 1L, 16L, 30L, 1L, 14L, 1L, 1L, 6L, 11L, 1L, 9L, 20L, 1L, 1L), 
end = c(22L, 13L, 24L, 27L, 16L, 30L, 51L, 14L, 26L, 8L, 6L, 11L, 17L, 9L, 20L, 26L, 17L, 14L), 
segment_id = c(1L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 1L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 1L)), 
row.names = 3377225:3377242, class = "data.frame", .Names = c("group_id", "start", "end", "segment_id"))


library(tidyverse)

my_df %>%
  mutate(start = ifelse(start > 1 , start + 1, start)) %>%          # update start values
  group_by(group_id, segment_id) %>%                                # for each group and segment id combination
  nest() %>%                                                        # create a dataset with the rest of the columns
  mutate(element_id_new = map(data, ~ seq(.$start, .$end, 1))) %>%  # get a sequence of values from start to end
  unnest(element_id_new)                                            # unnest the sequence

# # A tibble: 208 x 3
#   group_id segment_id element_id_new
#      <dbl>      <int>          <dbl>
# 1        1          1              1
# 2        1          1              2
# 3        1          1              3
# 4        1          1              4
# 5        1          1              5
# 6        1          1              6
# 7        1          1              7
# 8        1          1              8
# 9        1          1              9
# 10       1          1             10
# # ... with 198 more rows
变异(start=ifelse(start>1,start+1,start))%>%#更新开始值 每个组和段id组合的分组依据(组id,段id)%>%# nest()%>%#使用其余列创建一个数据集 mutate(element_id_new=map(data,~seq(.$start,.$end,1))%>%#从开始到结束获取一系列值 unest(元素_id _new)#取消序列的测试 ##A tibble:208 x 3 #组\u id段\u id元素\u id\u新建 # # 1 1 1 1 # 2 1 1 2 # 3 1 1 3 # 4 1 1 4 # 5 1 1 5 # 6 1 1 6 # 7 1 1 7 # 8 1 1 8 # 9 1 1 9 # 10 1 1 10 # # ... 还有198行
有一种使用
数据的替代方法。表

library(data.table)
setDT(my_df)[start == 1, start := 0][
  , .(group_id = rep(group_id, end - start), segment_id = rep(segment_id, end - start))][
      , element_id := rowid(group_id)][]
解释 请求的更正仅适用于
start==1
的少数条目,但方式与OP建议的不同。这减少了就地更新的数量,即不复制整个对象,并且我们可以避免在计算每个条纹的长度时添加
+1


然后,根据
结束-开始
的请求,重复
组id
段id
。最后,通过使用
rowid()
函数对每个
group\u id
中的行进行编号,来追加
元素的id

我发现在重塑数据集时,
start
end
值并不总是一致的。例如,对于
group_id=2
segment_id=2
,您有
start=13
,但在重塑的数据集中,它从14开始。这是一个模式还是一个错误?谢谢你的提问。这是一种“模式”,即对于所有元素_id>1,其思想是(;]数学区间。这意味着
元素\u id=13
在'segment\u id=1'中,
元素\u id=14
segment\u id=2
中。这是清楚的还是我应该改进解释?很好,我知道了。我将更新我的解决方案。然而,这里正好有元素\u id>1的这个模式,有一个不同的t dataset当element_id=1时,您可能会遇到这个问题,对吗?最好尝试找到一个更通用的解决方案。您是对的,我应该对mydf应用一些预处理,以避免模式/重叠。虽然我喜欢这个答案,但我认为这是问题的解决方案,输出与问题中的
solution_df
不匹配on.I trust
solution\u df
应该更正。@错误使用答案已更新。我认为通常的模式是,在组id内,每个段id不应该在下一个开始时完成。即使在更新答案后,我也会得到相同数量的行(208)。我知道了!我使用了错误的列名。我们正在更新元素ID,而不是段ID…:-)现在应该可以工作了。很好。我已经在我的代码中添加了您的预处理过程。这应该可以像预期的那样工作,并且比最后处理值快得多。非常感谢,我一直喜欢data.table解决方案,因为它们非常有效。我将执行基准测试并发布结果,以确定哪一个是最佳答案!谢谢,期待着查看您的BM结果,以及它们如何随问题大小而扩展。
my_df <- structure(list(group_id = c(1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 6, 6, 6, 7, 7, 7, 8, 9), 
start = c(1L, 1L, 13L, 24L, 1L, 16L, 30L, 1L, 14L, 1L, 1L, 6L, 11L, 1L, 9L, 20L, 1L, 1L), 
end = c(22L, 13L, 24L, 27L, 16L, 30L, 51L, 14L, 26L, 8L, 6L, 11L, 17L, 9L, 20L, 26L, 17L, 14L), 
segment_id = c(1L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 1L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 1L)), 
row.names = 3377225:3377242, class = "data.frame", .Names = c("group_id", "start", "end", "segment_id"))


library(tidyverse)

my_df %>%
  mutate(start = ifelse(start > 1 , start + 1, start)) %>%          # update start values
  group_by(group_id, segment_id) %>%                                # for each group and segment id combination
  nest() %>%                                                        # create a dataset with the rest of the columns
  mutate(element_id_new = map(data, ~ seq(.$start, .$end, 1))) %>%  # get a sequence of values from start to end
  unnest(element_id_new)                                            # unnest the sequence

# # A tibble: 208 x 3
#   group_id segment_id element_id_new
#      <dbl>      <int>          <dbl>
# 1        1          1              1
# 2        1          1              2
# 3        1          1              3
# 4        1          1              4
# 5        1          1              5
# 6        1          1              6
# 7        1          1              7
# 8        1          1              8
# 9        1          1              9
# 10       1          1             10
# # ... with 198 more rows
library(data.table)
setDT(my_df)[start == 1, start := 0][
  , .(group_id = rep(group_id, end - start), segment_id = rep(segment_id, end - start))][
      , element_id := rowid(group_id)][]
     group_id segment_id element_id
  1:        1          1          1
  2:        1          1          2
  3:        1          1          3
  4:        1          1          4
  5:        1          1          5
 ---                               
204:        9          1         10
205:        9          1         11
206:        9          1         12
207:        9          1         13
208:        9          1         14