我有一个以下类型的数据框
> foo <- data.frame(start = c(7, 12, 23, 30), end = c(10, 16, 27, 35), code = rep("A", 4))
> foo
start end code
1 7 10 A
2 12 16 A
3 23 27 A
4 30 35 A
我的目标是创建一个新的数据框series
,它扩展先前在开始/结束点压缩的有序系列,同时包含{{1}中编码区间之外的点的代码B. }}:
foo
非常感谢任何帮助。
答案 0 :(得分:3)
您可以使用Map
,这是lapply
的多变量版本:
foo2 <- do.call(rbind, Map(function(s, e, c){data.frame(time = seq(s, e),
code = c)},
foo$start, foo$end, foo$code))
head(foo2, 10)
# time code
# 1 7 A
# 2 8 A
# 3 9 A
# 4 10 A
# 5 12 A
# 6 13 A
# 7 14 A
# 8 15 A
# 9 16 A
# 10 23 A
该函数将time
作为seq
从start
添加到end
的数据框架和code
作为该行的代码。 do.call(rbind
捕获从每一行创建的data.frames并重新组合它们。
然后,我们可以使用merge
和is.na
填充剩余的级别:
foo3 <- merge(foo2, data.frame(time = 1:max(foo$end)), all.y = TRUE)
foo3$code <- as.character(foo3$code) # change from factor to character
foo3$code[is.na(foo3$code)] <- 'B'
head(foo3, 10)
# time code
# 1 1 B
# 2 2 B
# 3 3 B
# 4 4 B
# 5 5 B
# 6 6 B
# 7 7 A
# 8 8 A
# 9 9 A
# 10 10 A
如果您希望将数据保持为系数(合理),则可以在合并后替换两行:
foo3$code <- factor(foo3$code, levels = c('A', NA), labels = c('A', 'B'), exclude = NULL)
是等效的,除了将避免转换为vector。
如果你不介意code
是一个角色向量而你只有 得到的代码是&#34; A&#34;和&#34; B&#34;,您实际上可以从完整的data.frame向后工作,然后通过使用"A"
汇编序列重新插入apply
值,这有点简单:< / p>
foo4 <- data.frame(time = seq(1, max(foo$end)), code = 'B', stringsAsFactors = FALSE)
foo4$code[unlist(apply(foo[,1:2], 1, function(x){seq(x[1], x[2])}))] <- 'A'
答案 1 :(得分:2)
另一种选择,使用data.table
:
library(data.table)
# create a new table with time and code columns
bar <- data.table(time = 1:max(foo$end), code = "A")
# sub-assign "B" to code column
bar[!time %in% foo[,list(start:end), by = 1:nrow(foo)]$V1, code := "B"]
答案 2 :(得分:0)
使用一些sequence
和rep
吃:
out <- data.frame(
time=seq(1, max(foo$end)),
code="B",
stringsAsFactors=FALSE
)
cnts <- foo$end - foo$start + 1
out$code[sequence(cnts) + rep(foo$start, cnts) - 1] <- as.character(rep(foo$code, cnts))
out
# time code
#1 1 B
#2 2 B
#3 3 B
#4 4 B
#5 5 B
#6 6 B
#7 7 A
#8 8 A
#9 9 A
#10 10 A
#11 11 B
#...