r语言 - 用于根据与其他非 NA 行的接近程度获取行和的循环



我有一个包含 2 个重要列的数据集,PositionCount 。总共有 34,532 行,但Count列中只有 457 个非 NA 值(Position列中的每个单元格都有一个值)。我需要编写一个循环来向下行进,如果Count中有 2 行,它们之间只有 1 NA行,请将两个值相加并仅打印一行,其中包含求和的 Count 值和对应于较大 Count 值的位置值, 从而使三行合二为一。例如:

Position Count
15       15
22       NA
38       NA
49        5
55       NA
61       17

会成为

Position Count
15        15
22        NA
38        NA
61        22

完成此步骤后,我还需要编写另一个脚本来向下行进,并在 Count 中的非 NA 行之间查找只有两个 NA 的行。这将使以前的数据成为

Position Count
61        37

理想情况下,我想要一个可以灵活调整的循环,以适应可以自由更改的相邻非 NA 值之间的 NA 数量。我将非常感谢对此的任何见解。

如果我理解你想做什么,我认为这些功能应该为你服务。如果您愿意,您可以轻松地将removeAllNA()函数重写为循环而不是递归,但是在removeNA()中使用矢量化函数将比使用循环执行整个操作要快得多:

## df - data frame with Count and Position variables
## n - the number of consecutive NA values to rollup
removeNA <- function(df,n=1){
  #remove any leading NA values
  if(is.na(df$Count)[1]) df <- df[-(1:(which(!is.na(df$Count))[1]-1)),]
  #remove any ending NA values
  if(tail(is.na(df$Count),1)) df <- df[-(nrow(df):(tail(which(!is.na(df$Count)),1)+1)),]
  #get the indices for non NA values
  i <- which(!is.na(df$Count))
  #get the indices for the non NA values to rollup to based on the inputed "n"
  i <- i[diff(i) == n+1] + 1
  #return the data frame if no values to rollup
  if(length(i) == 0) return(df)
  #remove any values are out of range
  i <- i[i < nrow(df)]
  #rollup variables
  df$Count[i+n] <- df$Count[i+n] + df$Count[i-1]
  #remove variables that were included in rollup
  return(df[-c(sapply(1:n,function(x) i + x -1),i-1),])
}
removeAllNA <- function(df,n=1){
  if(!any(is.na(df$Count)) | n > nrow(df)){
    return(df)
  } else {
    df <- removeNA(df,n)
    removeAllNA(df,n+1)
  }
}

您的示例:

> tst <- data.frame(Position=c(15,22,38,49,55,61),Count=c(15,NA,NA,5,NA,17))
> removeNA(tst,1)
  Position Count
1       15    15
2       22    NA
3       38    NA
6       61    22
> removeNA(removeNA(tst,1),2)
  Position Count
6       61    37
> removeAllNA(tst)
  Position Count
6       61    37

更大的随机示例:

> set.seed(34)
> dat <- data.frame(Position=1:100,Count=round(runif(100,5,25)))
> dat$Count[sample(100,60)] <- NA
> removeAllNA(dat)
   Position Count
5         5    24
9         9    35
10       10    16
11       11    11
24       24    59
25       25    14
28       28    44
29       29    18
30       30    16
36       36    42
37       37     6
38       38    16
39       39    13
51       51    65
52       52    11
62       62    27
89       89    84
95       95    39
96       96    22
97       97     9

编辑:添加第二个功能:

addNotNA <- function(df){
  i <- which(!is.na(df$Count))
  i <- i[which(diff(i) == 1)] + 1
  if(length(i) == 0) return(df)
  df$Count[i] <- df$Count[i] + df$Count[i-1]
  return(df[-(i-1),])
}
> addNotNA(df)
  Position Count
2       22    36
3       38    NA
4       49     5
5       55    NA
6       61    17

最新更新