如何从数据框创建一个向量,该向量为每一行提供该行中“NA”(或自定义值)的列数以及上面的 n 行和<下面是em> m 行。
所以如果 m = n = 1(即每行中有多少列是NA并且前后都有NA),我的数据帧是
structure(list(X = 1:8, A = c(3L, NA, 10L, NA, 6L, NA, 5L, NA
), B = c(6L, NA, NA, NA, 8L, NA, 13L, NA), C = c(NA, 12L, 14L,
NA, NA, NA, 9L, NA), D = c(NA, NA, NA, NA, NA, 11L, 7L, NA)), .Names = c("X",
"A", "B", "C", "D"), class = "data.frame", row.names = c(NA,
-8L))
即
t X A B C D
1 1 3 6 NA NA
2 2 NA NA 12 NA
3 3 10 NA 14 NA
4 4 NA NA NA NA
5 5 6 8 NA NA
6 6 NA NA NA 11
7 7 5 13 9 7
8 8 NA NA NA NA
我想要矢量
count
0
1
2
1
1
0
0
0
(如果第一个和最后一个条目是NA
那就没问题)。我正在尝试模仿Excel中的COUNTIFS
函数,即第3行COUNTIFS(B2:F2,"",B3:F3,"",B4:F4,"")
。
答案 0 :(得分:3)
这应该产生预期的结果 -
y = is.na(yourDataFrame)
rowSums(y & rbind(rep(F,5), y[-nrow(yourDataFrame),]) & rbind(y[-1,], rep(F,5)))
答案 1 :(得分:2)
我想我明白你的意思。
假设数据框名为x
。
首先,对于row
中的每个(colum
,x
n),我们需要查看该单元格中是否有NA
和{{1}在{em>同一列之前的NA
行和n
行之后。
首先,让我们在单行的情况下这样做,行m
说。
我们还有i = 2
和n = 1
(来自问题中的示例)。
m = 1
如果当前值为NA i <- 2
n <- 1
m <- 1
,我们会计算行i - n
到i + m
的每列中的NAs数量(is.na
返回TRUE
给出列总和)
colSums
如果我们计算3 y <- colSums(is.na(x[(i - n):(i + m), ]))
# X A B C D
# 0 1 2 1 3
s(即此处只有D列符合条件),我们在前一行,当前行和下一行中只有一个NA
:
NA
所以符合我们标准的列的数字(因此是输出的y == n + m + 1
# X A B C D
# FALSE FALSE FALSE FALSE TRUE
元素)是:
i
然后我们可以使用sum(y == n + m + 1)
# 1
将其应用于每一行:
sapply
您还提到过您可能希望与自定义值进行比较,而不是countifs <- function (df, n, m) {
sapply(1:nrow(df),
function (i) {
nrows <- nrow(df)
startRow <- max(i - n, 1)
endRow <- min(i + m, nrows)
y <- colSums(is.na(x[startRow:endRow, ]))
sum(y == n + m + 1)
})
}
countifs(x, 1, 1)
# [1] 0 1 2 1 1 0 0 0
。在这种情况下,您可以NA
而不是is.na(x[...])
,而不是x[...] == value
是value
NA
,而您使用is.na
){ p>
此外,您只需使用行sapply
至n + 1
上的nrow(df) - m - 1
并设置第一个n
和最后m
个元素,即可节省一些工作量自动为0。
答案 2 :(得分:2)
此功能可识别NA
length = .length
值
foo <- function(x,.length){
x <- is.na(x)
if( .length < 2L ||.length %%2L == 0L ){stop('.length must be an odd number greater than 2')}
lx <- length(x)
if(lx <.length) {return(rep_len(FALSE, lx))}
midpoints <- seq.int(2L, lx-1L, by = 1L)
c(FALSE,sapply(midpoints, function(xx) all(x[(xx-1L):(xx+1L)])),FALSE)
}
我们可以将它与rowSums和sapply
一起使用,以获得您想要的效果。
rowSums(sapply(xx, foo, .length = 3))
## [1] 0 1 2 1 1 0 0 0
或者您可以使用rollapply
包
zoo
library(zoo)
rowSums(sapply(xx, function(x) {
rollapply(is.na(x), width = 3, fill = FALSE, FUN = all)
}))
甚至只是
rowSums(rollapply(is.na(xx),width=3, FUN=all, fill = FALSE))
答案 3 :(得分:1)
您可以使用describe
来获取每列中的NA数量。
describe(traindata)
输出如下:
Column_3
n missing unique Mean .05 .10 .25 .50 .75 .90 .95
646 23 283 0.2792 0.0000 0.0000 0.0000 0.1455 0.4798 0.9305 1.0000
检查missing
值。
答案 4 :(得分:1)
我无法想出一个矢量化版本,所以这里有一个使用旧的for循环:
x <- structure(list(X = 1:8, A = c(3L, NA, 10L, NA, 6L, NA, 5L, NA
), B = c(6L, NA, NA, NA, 8L, NA, 13L, NA), C = c(NA, 12L, 14L,
NA, NA, NA, 9L, NA), D = c(NA, NA, NA, NA, NA, 11L, 7L, NA)), .Names = c("X",
"A", "B", "C", "D"), class = "data.frame", row.names = c(NA,
-8L))
y <- x
y[is.na(y)] <- -99
out <- vector("numeric", nrow(y))
n <- 1
m <- 1
for (c in (1+n):(nrow(y)-m)) {
out[c] <- sum((y[(c-n),] == -99) & (y[(c),] == -99) & (y[(c+m),] == -99))
}
out
这应该可以解决问题(即使允许使用n和m):
> out
[1] 0 1 2 1 1 0 0 0
请注意,我使用了两个技巧。由于使用NA
s是有问题的,我将它们与-99
交换(虽然这不是完全必要的)。然后我不会遍历前n行和后m行。
如果有人提出了矢量化版本,他/她肯定会得到我的赞成。