重建/扩展先前在每个组ID内的子组ID上折叠的data.frame
这个问题是问你如何“重建”一个数据框,该数据框以前是基于段id折叠的,包含开始变量和结束变量,并放入一个表中,该表在每个间隔内扩展到每个元素 考虑以下示例数据集:重建/扩展先前在每个组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
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 trustsolution\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