【问题标题】:removing sequences of positive values between sequences of "0"删除“0”序列之间的正值序列
【发布时间】:2014-08-19 12:45:47
【问题描述】:

我想在数据框中创建一个小函数,用于检测(并设置为 0)位于等于 0 的值序列之间的正值序列,但前提是这些正值序列不超过长度超过 5 个值。

这里只是一个小例子,向您展示我的数据看起来如何(initial_data 列),以及我想在最后获得什么(final_data 列):

DF<-data.frame(initial_data=c(0,0,0,0,100,2,85,0,0,0,0,0,0,3,455,24,10,7,6,15,42,0,0,0,0,0,0,0),final_data=c(0,0,0,0,0,0,0,0,0,0,0,0,0,3,455,24,10,7,6,15,42,0,0,0,0,0,0,0))

这句话也可以恢复诀窍: "如果有一个正值序列,不超过 5 个值,并且位于至少两个或三个 0 值之间(在这个正值序列之前和之后),那么也将该序列设置为 0"

有什么建议可以轻松做到这一点吗?

非常感谢!!!

【问题讨论】:

  • 序列中可以有负值还是只有0和正值?
  • 不,在这种情况下只有 0 和正值。此示例用于雪深数据

标签: r


【解决方案1】:

这是使用rle 函数的可能方法:

DF<-data.frame(initial_data=c(0,0,0,0,100,2,85,0,0,0,0,0,0,3,455,24,10,7,6,15,42,0,0,0,0,0,0,0),
               final_data=c(0,0,0,0,0,0,0,0,0,0,0,0,0,3,455,24,10,7,6,15,42,0,0,0,0,0,0,0))

# using rle create an object with the sequences of consecutive elements 
# having the same sign (-1 means negative, 0 means zero, 1 means positive)
enc <- rle(sign(DF$initial_data))

# find the positive sequences having maximum 5 elements
posSequences <- which(enc$values == 1 & enc$lengths <= 5)

# remove index=1 or index=length(enc$values) if present because 
# they can't be surrounded by 0
posSequences <- posSequences[posSequences != 1 & 
                             posSequences != length(enc$values)]

# check if they're preceeded and followed by at least 2 zeros 
# (if not remove the index)
toForceToZero <- sapply(posSequences,FUN=function(idx){
                                           enc$values[idx-1]==0 &&
                                           enc$lengths[idx-1] >= 2 && 
                                           enc$values[idx+1] == 0 &&
                                           enc$lengths[idx+1] >= 2})
posSequences <- posSequences[toForceToZero]

# reverse the run-length encoding, setting NA where we want to force to zero
v <- enc$values
v[posSequences] <- NA

# create the final data vector by forcing NAs to 0  
final_data <- DF$initial_data
final_data[is.na(rep.int(v, enc$lengths))] <- 0

# check if is equal to your desired output
all(DF$final_data == final_data)

# > [1] TRUE

【讨论】:

  • 忘记检查周围零的数量。已编辑。
【解决方案2】:

我最好的朋友rle 来救援:

notzero<-rle(as.logical(unlist(DF)))
Run Length Encoding
  lengths: int [1:7] 4 3 6 8 20 8 7
  values : logi [1:7] FALSE TRUE FALSE TRUE FALSE TRUE ...

现在只需找到valuesTRUElengths values 替换为FALSE。然后调用inverse.rle 得到想要的输出。

【讨论】:

  • 如果您可以扩展您的答案(“现在只需查找所有位置...”)以查看如何获得所需的结果,那将会很有趣,因为您还需要照顾如果我理解问题正确的话,正数序列前后的零个数。
  • @beginneR 是的,但是 digEmAll 似乎已经为我完成了所有艰苦的工作。我会接受他的回答而不是我的回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-04-10
  • 2016-07-28
  • 2020-10-24
  • 2017-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多