如何解决R:完成序列列并填充行
我从一个数据集开始,它有一个数字列(在我的例子中是时间,但采用数字格式)、时间戳的某个事件和一个 ID。我希望运行一些代码来扩展数据框以填充数字序列,同时复制事件列(和任何其他相关列)。我想通过 ID 运行它,所以我不会同时填补 ID 之间的空白。
这是我开始使用的数据的简化示例。我想分别填充每个 ID 的“值”列的序列,用每个“事件”的第一行的数据完成每个新行。
a<-c("162","164","169","171","174","188","191","198","200")
b<-c("start1","end1","start2","event","end2","start1","end2")
c<-c("A","A","B","B")
original<-data.table(value = a,event = b,ID = c)
这是我最终目标的重构:
agoal<-c(seq(from = 162,to = 174),seq(from = 188,to = 200))
bgoal<-c("start1","end2")
cgoal<-c(rep("A",13),rep("B",13))
goal<-data.table(value = agoal,event = bgoal,ID = cgoal)
对不起,如果不是很清楚!
解决方法
我们可以使用 complete
包中的 fill
和 tidyr
:
首先使用 tpye.convert(as.is=TRUE)
将数字分配给 value
library(dplyr)
library(tidyr)
original %>%
type.convert(as.is=TRUE) %>%
group_by(ID) %>%
complete(value = first(value):max(value)) %>%
fill(event)
输出:
value event ID
1: 162 start1 A
2: 163 start1 A
3: 164 end1 A
4: 165 end1 A
5: 166 end1 A
6: 167 end1 A
7: 168 end1 A
8: 169 start2 A
9: 170 start2 A
10: 171 event A
11: 172 end2 A
12: 173 end2 A
13: 174 end2 A
14: 188 start1 B
15: 189 start1 B
16: 190 start1 B
17: 191 end1 B
18: 192 end1 B
19: 193 end1 B
20: 194 end1 B
21: 195 end1 B
22: 196 end1 B
23: 197 end1 B
24: 198 start2 B
25: 199 start2 B
26: 200 end2 B
,
有两个部分需要处理:a) 如何为 value
列中缺失的数字添加行和 b) 如何用之前的任何内容填充 event
。 (b) 很简单(只需使用 fill
)。 (a) 可以通过使用您想要的所有值创建一个新数据框并加入原始数据框来完成:
library(tidyverse)
original %>%
group_by(ID) %>%
summarize(a = as.integer(min(value)),b = as.integer(max(value))) %>%
transpose() %>%
map(~ data.frame(ID = .x$ID,value = .x$a:.x$b)) %>%
reduce(bind_rows) %>%
left_join(original,by = c("value","ID")) %>%
group_by(ID) %>%
fill(event,.direction = "down")
循序渐进:
- 获取每个组内
value
列的最小值和最大值 - 使用
transpose
将数据框拆分为一个列表(这将给出一个嵌套列表,其中第一级按行号索引,第二级按列名索引) - 使用
map
为每个 ID 制作一个数据框列表,其中value
列包含原始最小值和最大值之间的所有值 - 使用
reduce
和bind_rows
将所有数据帧混合在一起 - 使用
value
和ID
加入原件;请注意,left_join
将确保所有新的value
和ID
组合都存在,即使它们在原始组合中没有任何对应的组合(这将导致任何丢失的 {{1} } 具有 NA 的值,这是您下一步想要的) - 将所有 NA 向下填充该组中的前一个事件
结果:
event
请注意,如果您将数值作为 ID value event
1 A 162 start1
2 A 163 start1
3 A 164 end1
4 A 165 end1
5 A 166 end1
6 A 167 end1
7 A 168 end1
8 A 169 start2
9 A 170 start2
10 A 171 event
11 A 172 event
12 A 173 event
13 A 174 end2
14 B 188 start1
15 B 189 start1
16 B 190 start1
17 B 191 end1
18 B 192 end1
19 B 193 end1
20 B 194 end1
21 B 195 end1
22 B 196 end1
23 B 197 end1
24 B 198 start2
25 B 199 start2
26 B 200 end2
中的实际数字,则您实际上并不需要这两个 as.integer
调用。另外,我认为在 OP 中您打算连续使用 original
三次而不是一次(否则模式会被破坏)。
另一个使用 dplyr
和 tidyr
的选项:
library(dplyr)
library(tidyr)
original %>%
split(.$ID) %>%
lapply(function(x) data.frame(value = as.character(seq(min(x$value),max(x$value)))) %>%
left_join(x,by="value") %>%
fill(c("event","ID"))) %>%
do.call(rbind.data.frame,.)
返回
value event ID
A.1 162 start1 A
A.2 163 start1 A
A.3 164 end1 A
A.4 165 end1 A
A.5 166 end1 A
A.6 167 end1 A
A.7 168 end1 A
A.8 169 start2 A
A.9 170 start2 A
A.10 171 event A
A.11 172 event A
A.12 173 event A
A.13 174 end2 A
B.1 188 start1 B
B.2 189 start1 B
B.3 190 start1 B
B.4 191 end1 B
B.5 192 end1 B
B.6 193 end1 B
B.7 194 end1 B
B.8 195 end1 B
B.9 196 end1 B
B.10 197 end1 B
B.11 198 start2 B
B.12 199 start2 B
B.13 200 end2 B
大致相同,但没有 split
和 do.call
部分:
original %>%
group_by(ID) %>%
group_map(function(x,...) data.frame(value = as.character(seq(min(x$value),max(x$value)))) %>%
left_join(original,"ID"))) %>%
bind_rows()
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。