首页 > 解决方案 > 用数据框 (R) 中的 NA 替换 X 个连续重复的零值

问题描述

我有一个数据框,其中包含几个用户的每日价值。用户有不同的开始日期,因此我为第一次使用之前的值分配了 NA,为此后没有值的任何单元格分配了零值。我使用以下循环来执行此操作:

for (i in seq_along(df)) {
 isna <- is.na(df[[i]])
 nonna <- match(FALSE,isna)
 id <- which(isna)
 df[[i]][id[id>nonna]] <- 0
}

但是,有些用户在接近尾声时有很多零值,表明他们已经停止使用该服务。如果数据帧末尾有超过 100 个零值,我也想将这些值设置为 NA。我没有成功地做到这一点,任何建议将不胜感激。

标签: rna

解决方案


我想我理解你的问题,所以让我重述一遍,如果我错了,你可以告诉我。

您有一个数据框,其中列代表用户,行代表天。因此,从数据框中取出一列df[[i]]将为您提供一个用户活动的时间序列。

用户并非都在同一天开始,因此其中一些时间序列可能有很长的初始0活动运行。这表明用户还没有使用您的服务,应该是NA0 而不是 0。因此我们可以假设在第一个非零数字的日期之前的所有内容都应该是NA.

一些用户在加入您的服务后的几天内有 0 个活动。这只是意味着他们那天没有使用您的服务。但是,如果他们完全离开您的服务,他们将生成一长串零,直到他们离开时的列末尾。

一些用户可能偶然在数据帧末尾有几个 0 - 他们没有离开服务,只是在数据帧停止的时间点恰好有几天没有使用它。这些 0 不应转换为NA值。但是,如果用户在其列末尾有超过 100 天的连续零活动,则末尾的所有零都应转换为NA.

假设这就是您的意思,并且假设NA您的列中没有值开始,我们可以解决运行长度编码的问题。我已经评论了每一行,所以你可以遵循逻辑:

for(i in length(df))
{
  user <- df[[i]]               # Write the column to a new vector for clarity
  
  MAX      <- 100               # Set the maximum number of 0s allowed at the end
  user_rle <- rle(user)         # Get run length encoding of the column
  lens     <- user_rle$lengths  # Extract the run-length encoding lengths
  vals     <- user_rle$values   # Extract the run-length encoding values
  last     <- length(lens)      # For clarity of code, make alias for last index of rle
  
  if(vals[1] == 0) {            # If zeros at the start...
    user[seq(lens[1])] <- NA    # Replace with NA
  }
  
  if(vals[last] == 0 & lens[last] > MAX) {           # If more than 100 0s at end
    user[(-lens[last] + 1):0 + length(user)] <- NA   # Replace with NA
  }
  
  df[[i]] <- user               # Write the vector back in to the data frame
}

请注意,有更有效的方法可以使用更少的代码来做到这一点,但这是为了易于遵循。


推荐阅读