R—在每一行计算“";"街坊",;只含钠的

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,

如何从数据帧创建一个向量,为每行提供该行中“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, 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行
column
j
:如果第
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))