我有一个包含 2 个重要列的数据集,Position
和 Count
。总共有 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