R—在每一行计算“";"街坊",;只含钠的
如何从数据帧创建一个向量,为每行提供该行中“NA”(或自定义值)的列数,以及上面的n行和下面的m行 因此,如果m=n=1(即,每行中有多少列是NA,并且前后都有NA),那么我的数据帧是R—在每一行计算“";"街坊",;只含钠的,r,apply,R,Apply,如何从数据帧创建一个向量,为每行提供该行中“NA”(或自定义值)的列数,以及上面的n行和下面的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,
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))
i、 e
我要向量
count
0
1
2
1
1
0
0
0
(如果第一个和最后一个条目是
NA
,则可以)。我试图在Excel中模拟一个COUNTIFS
函数,即第3行的COUNTIFS(B2:F2,“,B3:F3,”,B4:F4,“”
您可以使用description
来获取每列中的NAs数量
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
检查是否缺少
值。我无法找到矢量化版本,因此这里有一个使用良好的旧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
注意,我使用了两个技巧。由于使用NA
s是有问题的,我将它们与-99
交换(尽管这不是完全必要的)。然后我不在前n行和最后m行上循环
如果有人提出矢量化版本,他/她肯定会得到我的支持。我想我明白你的意思
假设数据帧被称为x
首先,对于x
中的每个(row
,column
n),我们需要查看该单元格中是否有NA
,以及前面和后面的n
行是否在同一列中有NA
首先,让我们在一行的情况下这样做,行i=2
say。
我们还有n=1
和m=1
(来自问题中的示例)
现在,如果我们计算了3个NA
s(即,此处仅D列符合条件),则上一行、当前行和下一行中只有一个NA
:
因此,满足我们标准的列数(因此输出的i
th元素)为:
然后,我们可以使用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
countifs这将产生预期的结果-
y = is.na(yourDataFrame)
rowSums(y & rbind(rep(F,5), y[-nrow(yourDataFrame),]) & rbind(y[-1,], rep(F,5)))
这是一个函数,它将识别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)
}
没有重新发明轮子(滚动的东西)
或者您可以使用zoo
软件包中的rollapply
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))
我不明白你的描述是如何产生预期结果的。为什么第2行的计数为1?第D列的第2行、第1行和第3行的计数为NA。其他列没有,所以count
是1。@Henrik我想他们的意思是:假设我们看一看第I行columnj
:如果第j列n行之前和第m行之后的行I
,我们计算它。因此,对于第二行,只有“D”列中的NA
在其正上方和正下方有一个NA
。是的,Mathematic.coffee是正确的。@Hugh我可以澄清一下吗?在第1行中,D列中的NA后面有一个NA,但之前没有,因为没有上一行-您希望它始终返回0吗?(即,count
向量的第一个和最后一个元素始终为0?)我认为这不适用于此。我需要知道NA条件的行位置,而不仅仅是每列出现此条件的总数。对不起,我的标题让人困惑。是的,这解决了*n*=*m*=1的问题。(一般情况下可能要求过高。)您选择-99有什么特别的原因吗?正如上面Mathematic.coffee所指出的,这里使用m
和n
是不正确的。改为使用rollappy
。所有答案都非常有用,但这回答了所有问题。非常感谢。哇!我印象深刻。这是一个使用m
和n
的版本:行和(y&rbind(matrix(FALSE,nrow=m,ncol=5),y[-((length(yourDataFrame)-(m-1)):length(yourDataFrame)),])&rbind(y[-(1:n),],matrix(FALSE,nrow=n,ncol=5))
@Henrik no,您的版本统计列n
之前和m
之后的行为NA的行数,而不是从n
之前到m
之后的所有行为NA的行数(在该列中)。非常喜欢这个答案的圆滑,但不幸的是,它不能扩展到任意的n
和m
@mathematic.coffee同意。我在描述中漏掉了那一点。而且似乎很难使这个解决方案适应期望的行为。
sum(y == n + m + 1)
# 1
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
y = is.na(yourDataFrame)
rowSums(y & rbind(rep(F,5), y[-nrow(yourDataFrame),]) & rbind(y[-1,], rep(F,5)))
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(xx, foo, .length = 3))
## [1] 0 1 2 1 1 0 0 0
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))