答案 0 :(得分:2)
使用此示例数据:
df <- data.frame(
Range1 = c(1, 2, 3, 5, 10, 12, 16, 20, 21, 28, 33),
Range2 = c(2, 3, 5, 10, 12, 16, 20, 21, 28, 33, 40),
Breakpoint = c("", "", "", "Y", "", "Y", "", "", "Y", "", ""))
尾随切为的解决方案是:
首先切断悬空的位:
df2 = df[1:max(which(df$Breakpoint=="Y")),]
然后算出每组的长度:
> rgroup=rle(rev(cumsum(rev(df2$Break=="Y"))))$lengths
获取Y的位置:
> Ypos = which(df2$Breakpoint=="Y")
构造一个索引向量,该向量是Y位置减去从1到块的长度的反向序列。子集:
> df2[rep(Ypos, rgroup) - unlist(lapply(rgroup,function(x){1:x})) +1,]
Range1 Range2 Breakpoint
4 5 10 Y
3 3 5
2 2 3
1 1 2
6 12 16 Y
5 10 12
9 21 28 Y
8 20 21
7 16 20
根据需要重新添加悬挂位。
[编辑-上面添加了新版本。以下出于历史目的的代码]
我的旧版本是这个版本,并且处理了一些悬空的比特:
> group=rev(cumsum(rev(df$Break=="Y")))
> rbind(do.call(rbind,lapply(split(df[group>0,],-group[group>0]),function(x){x[nrow(x):1,,drop=FALSE]}))[,c("Range1","Range2")],df[max(which(df$Break=="Y")),1:2,drop=FALSE],df[group==0,1:2])
并获得:
Range1 Range2
-3.4 5 10
-3.3 3 5
-3.2 2 3
-3.1 1 2
-2.6 12 16
-2.5 10 12
-1.9 21 28
-1.8 20 21
-1.7 16 20
9 21 28
10 28 33
11 33 40
如果您不喜欢行名,请删除它们。仅使用基本R函数。
我不确定在上一次休息之后是否没有任何遗留问题,是否可以解决这个问题,但是如果发生这种情况,您还没有很好地说明问题。
> group=rev(cumsum(rev(df$Break=="Y")))
这将创建一个向量,该向量从最后一行的0开始,并在每次找到Y时增加。将其取反以获取直到每个Y的块的分组变量。
由于我将要发表评论,因此如果进行剪贴,这点将不起作用:
> rbind(
# we need to bind three things. The reversed chunks, the last break point and
# the trailing stuff:
do.call(
# the trailing stuff is the rbind of the reversed chunks:
rbind,
# split the data into a list of chunks
lapply(
split(df[group>0,],-group[group>0]),
# reverse them
function(x){x[nrow(x):1,,drop=FALSE]}
# and only take the columns we need:
))[,c("Range1","Range2")],
# this is the last Y
df[max(which(df$Break=="Y")),1:2,drop=FALSE],
# this is the trailing rows, get them in order they appear:
df[group==0,1:2])
像这样进行注释使我看到可以进行的一些优化,但仅此而已。
答案 1 :(得分:0)
取决于data.frame的大小,这可以通过for循环手动完成。
BreakPoints <- which(!is.na(DF$`break point`))
if(length(breakPoints) > 0){
startIndex <- 1 #Startindex tells me where i should point the breakPoint
for(i in breakPoints){ #Iterate over breakpoints
#Put the break point at the startIndex row
DF[startIndex:i,] <- DF[c(i, startIndex:(i-1), ]
#Update the placement as the next block
startIndex <- i + 1
}
}
如果您的数据很大,则可能有一种更有效的方法。通常,与其他方法相比,通过[<-.dataframe
进行子设置的速度较慢。最初的优化程序可能只是将上面的代码转换为data.table
格式,而子集要快得多。