在某些其他案件后删除案件

时间:2017-05-03 19:00:49

标签: r

我有一个数据框,比如说

df = data.frame(x = c("a","a","b","b","b","c","d","t","c","b","t","c","t","a","a","b","d","t","t","c"), 
                y = c(2,4,5,2,6,2,4,5,2,6,2,4,5,2,6,2,4,5,2,6))

我想只删除td之间直接位于其中的一个或多个c的行,在其他所有情况下我都希望保留这些情况。所以对于这个例子,我想删除第8,18和19行的t,但保留其他的。我有成千上万的案例,所以手动这样做将是一个真正的恐怖。非常感谢任何帮助。

3 个答案:

答案 0 :(得分:1)

一种选择是使用rle来获取相同字符串的运行,然后您可以使用sapply检查前进/后退并返回您要删除的所有位置:

rle_vals <- rle(as.character(df$x))

drop <- unlist(sapply(2:length(rle_vals$values), #loop over values
                      function(i, vals, lengths) {
                        if(vals[i] == "t" & vals[i-1] == "d" & vals[i+1] == "c"){#Check if value is "t", previous is "d" and next is "c"
                          (sum(lengths[1:i-1]) + 1):sum(lengths[1:i]) #Get row #s
                        }
                      },vals = rle_vals$values, lengths = rle_vals$lengths))

drop
#[1]  8 18 19

df[-drop,]
#   x y
#1  a 2
#2  a 4
#3  b 5
#4  b 2
#5  b 6
#6  c 2
#7  d 4
#9  c 2
#10 b 6
#11 t 2
#12 c 4
#13 t 5
#14 a 2
#15 a 6
#16 b 2
#17 d 4
#20 c 6

答案 1 :(得分:1)

这也可以通过折叠到一个字符串,识别d和c之间的t组(或c和d - 不确定你是否也想要这个选项),然后确定它们的位置并删除适当的行。

df =        data.frame(x=c("a","a","b","b","b","c","d","t","c","b","t","c","t","a","a","b","d","t","t","c"),
                y=c(2,4,5,2,6,2,4,5,2,6,2,4,5,2,6,2,4,5,2,6),stringsAsFactors = FALSE)

dfs <- paste0(df$x,collapse="") #collapse to a string
dfs2 <- do.call(rbind,lapply(list(gregexpr("dt+c",dfs),gregexpr("ct+d",dfs)),
                function(L) data.frame(x=L[[1]],y=attr(L[[1]],"match.length"))))
dfs2 <- dfs2[dfs2$x>0,] #remove any -1 values (if string not found)
drop <- unlist(mapply(function(a,b) (a+1):(a+b-2),dfs2$x,dfs2$y))
df2 <- df[-drop,]

答案 2 :(得分:0)

以下是基础R的另一种解决方案:

df = data.frame(x = c("a","a","b","b","b","c","d","t","c","b","t","c","t","a","a","b","d","t","t","c"), 
                y = c(2,4,5,2,6,2,4,5,2,6,2,4,5,2,6,2,4,5,2,6))

#
s <- paste0(df$x, collapse="")
L <- c(NA, NA)
while (TRUE) {
  r <- regexec("dt+c", s)[[1]]
  if (r[1]==-1) break
  L <- rbind(L, c(pos=r[1]+1, length=attr(r, "match.length")-2))
  s <- sub("d(t+)c", "x\\1x", s)
}
L <- L[-1,]
drop <- unlist(apply(L,1, function(x) seq(from=x[1], len=x[2])))
df[-drop, ]
# > drop
# 8 18 19 
# > df[-drop, ]
# x y
# 1  a 2
# 2  a 4
# 3  b 5
# 4  b 2
# 5  b 6
# 6  c 2
# 7  d 4
# 9  c 2
# 10 b 6
# 11 t 2
# 12 c 4
# 13 t 5
# 14 a 2
# 15 a 6
# 16 b 2
# 17 d 4
# 20 c 6

gregexpr()更短:

s <- paste0(df$x, collapse="")
g <- gregexpr("dt+c", s)[[1]]
L <- data.frame(pos=g+1, length=attr(g, "match.length")-2)
drop <- unlist(apply(L,1, function(x) seq(from=x[1], len=x[2])))
df[-drop, ]