删除部分缺失值的行和列

6

I have the following dataframe (s):

s<-read.table(text = "V1    V2  V3  V4  V5  V6  V7  V8  V9  V10 
  1 0   62  64  44  NA  55  81  66  57  53  
  2 0   0   65  50  NA  56  79  69  52  55  
  3 0   0   0   57  NA  62  84  76  65  59  
  4 0   0   0   0   NA  30  70  61  41  36  
  5 0   0   0   0   NA  NA  NA  NA  NA  NA  
  6 0   0   0   0   0   0   66  63  51  44  
  7 0   0   0   0   0   0   0   80  72  72  
  8 0   0   0   0   0   0   0   0   68  64  
  9 0   0   0   0   0   0   0   0   0   47  
  10    0   0   0   0   0   0   0   0   0   0   ", header = TRUE)

可以看到,在这个例子中第5行和第5列只包含NA0值。我想要省略它们,并保持行列的顺序。可能会有更多的行与列遵循相同的规律,我也想做同样的处理。数据框的大小可能会改变。

最终结果如下:

    V1  V2  V3  V4  V6  V7  V8  V9  V10 
1   0   62  64  44  55  81  66  57  53  
2   0   0   65  50  56  79  69  52  55  
3   0   0   0   57  62  84  76  65  59  
4   0   0   0   0   30  70  61  41  36  
6   0   0   0   0   0   66  63  51  44  
7   0   0   0   0   0   0   80  72  72  
8   0   0   0   0   0   0   0   68  64  
9   0   0   0   0   0   0   0   0   47  
10  0   0   0   0   0   0   0   0   0   

有没有办法同时获取省略的行和列号码(在此例中为5)?

1
那么,什么是最小的NA数量,可以证明需要删除一行/列。所有非NA值都必须为0才能删除吗? - Serban Tanasa
可以看出这是一个上三角矩阵。在每种情况下,NA将出现在行中:从行号列到最后一列(end)。对于相同的列号:从第一行到相同的行号(本例中为5)。 - Avi
这可能很明显,但是:你应该使用矩阵而不是数据框。 - Frank
我使用矩阵。如果您能展示一个输入矩阵的答案而无需转换为数据框,我会很高兴。 - Avi
有没有办法获取被省略的行和列(在这种情况下是5)? - Avi
4个回答

4

您需要更明确地定义何时要放弃。在这种情况下,矩阵一侧和对角线始终为0。

然而,一般来说,我会使用以下方法:

s[!rowSums(is.na(s))>1,!colSums(is.na(s))>1]

考虑0的情况

s[!rowSums(is.na(s)|s==0)>9,!colSums(is.na(s)|s==0)>9]

3
我们可以尝试。
v1 <- colSums(is.na(s))
v2 <- colSums(s==0, na.rm=TRUE)
j1 <- !(v1>0 & (v1+v2)==nrow(s) & v2 >0)

v3 <- rowSums(is.na(s))
v4 <- rowSums(s==0, na.rm=TRUE)
i1 <- !(v3>0 & (v3+v4)==ncol(s) & v3 >0)
s[i1, j1]
#   V1 V2 V3 V4 V6 V7 V8 V9 V10
#1   0 62 64 44 55 81 66 57  53
#2   0  0 65 50 56 79 69 52  55
#3   0  0  0 57 62 84 76 65  59
#4   0  0  0  0 30 70 61 41  36
#6   0  0  0  0  0 66 63 51  44
#7   0  0  0  0  0  0 80 72  72
#8   0  0  0  0  0  0  0 68  64
#9   0  0  0  0  0  0  0  0  47
#10  0  0  0  0  0  0  0  0   0

假设我们改变了 's' 中的一个值
 s$V7[3] <- NA

通过运行上面的代码,输出结果将会是:
#   V1 V2 V3 V4 V6 V7 V8 V9 V10
#1   0 62 64 44 55 81 66 57  53
#2   0  0 65 50 56 79 69 52  55
#3   0  0  0 57 62 NA 76 65  59
#4   0  0  0  0 30 70 61 41  36
#6   0  0  0  0  0 66 63 51  44
#7   0  0  0  0  0  0 80 72  72
#8   0  0  0  0  0  0  0 68  64
#9   0  0  0  0  0  0  0  0  47
#10  0  0  0  0  0  0  0  0   0

注意:OP的条件仅包括NA和0值。我希望将它们省略。


3
我本来想建议:
sclean <- s[rowSums(s == 0|is.na(s)) != ncol(s) | (rowSums(s == 0, na.rm=TRUE) == ncol(s)),
        colSums(s == 0|is.na(s) )!= nrow(s) | colSums(s == 0, na.rm=TRUE) == nrow(s)]

我认为这不正确,因为答案基于大于1的NA值。它可能有多个非NA(除0以外)的NA值。例如,如果我们执行s$V7[3] <- NA,那么它会省略该列,而我的解决方案则保留它。 - akrun
1
@Avi 添加了保留0列的条件。 - Serban Tanasa
@akrun,根据我的解决方案,在你的测试用例中似乎保留了v7。 - Serban Tanasa

1
您可以尝试以下操作:

myRowSums <- rowSums(is.na(s) | s == 0)
myColSums <- colSums(is.na(s) | s == 0)

sSmall <- s[which(myRowSums != ncol(s)), which(myColSums != nrow(s))]

它适用于以下数据集,删除完全由0和NA组成的所有列和行。
s <- data.frame(a=c(0, rnorm(5), 0), b=c(0, rnorm(2), NA, NA,1, NA), c=c(rep(c(0,NA), 3), 0))

1
尝试 sSmall <- s[myRowSums != ncol(s), myColSums!= nrow(s)] - Serban Tanasa
感谢@SerbanTanasa。我得处理几个错别字。 - lmo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接