b <- c("true", "true", "true", "true", "true", "false", "false", "true","true", "true", "false", "false", "false","true", "true", "false", "true", "false", "true", "false")
我尝试编写一个函数,将上面的向量作为输入,并在每个&#中找到所需字符串的第一次和最后一次出现的索引(例如&#34; true&#34;) 39;区&#39; (区域被定义为具有两个或更多个连续相同元素的子向量)。上述所需的输出将是数据帧,例如:
x | y
----|----
1 | 5
8 | 10
14 | 15
我已经成功编写了一个功能(如下所示),但这对我的Shiny应用来说需要太长时间。如果有更清洁,更快捷的方法,那将会很棒。
zone_identifier <- function(dataframe, zone_source_col_index, match_string){
zones_df <- data.frame()
zone_source_vector <- data.frame[,zone_source_col_index]
for(i in 1:(length(zone_source_vector)-1){
zone_component_recorder <-vector()
for(j in 1:(length(zone_source_vector)-i)){
if(zone_source_vector[i]==match_string && zone_source_vector[i+j]==match_string){ if(i>1 && zone_source_vector[i-1]==match_string{
break}
zone_component_recorder <-c(i, i+j)
else if(zone_source_vector[i]==match_string && zone_source_vector[i+j]!=match_string){break}
zones_df <- rbind.data.frame(zones_df, zone_component_recorder)}
return(zones_df)
}
答案 0 :(得分:4)
您可以使用rle
查找解决方案
#use rle to find runs of same value in b
rle_res=rle(b)
#find starting position of each true and false
start_vec=c(1,1+cumsum(rle_res$lengths))
start_vec=start_vec[-length(start_vec)]
#same for end position
end_vec=c(start_vec[-1]-1,NA_integer_)
#filter on true values
data.frame(x=start_vec[rle_res$values=="true"],
y=end_vec[rle_res$values=="true"])
# x y
#1 1 5
#2 8 10
#3 14 15
#4 17 17
#5 19 19
答案 1 :(得分:2)
以下是使用data.table
library(data.table)
v1 <- data.table(b)[, {
i1 <- .I[b=="true" & seq_len(.N) %in% c(1,.N)]
if(.N==1) rep(i1, 2) else i1} , by = rleid(b)]$V1
data.table(x= v1[c(TRUE, FALSE)], y = v1[c(FALSE, TRUE)])
# x y
#1: 1 5
#2: 8 10
#3: 14 15
#4: 17 17
#5: 19 19
答案 2 :(得分:2)
使用dplyr的解决方案
library(dplyr)
run <- rle(b)$lengths
data.frame( type= rle(b)$values ,
x =c(1,cumsum(run)[-length(run)]+1 ) ,
y =cumsum(run) ) %>%
filter(type=="true") %>%
select(-type)