如何按列删除所有具有“NA”值的单元格

dig*_*git 4 r

这个问题不是重复的,因为我的data.frame 不同NA in all Columns and therefore the solution mentioned in that question does not work.

我有data.frame很多NA值,我想删除所有具有 NA 值的单元格(重要:不是行或列,单元格)。原来的样子是这样的:

A  B
1  NA
NA 2
2  NA
NA NA
NA NA
NA 4
3  5
Run Code Online (Sandbox Code Playgroud)

期望的结果如下所示:

A  B
1  2
2  4 
3  5
Run Code Online (Sandbox Code Playgroud)

列数必须保持相同,但值是否保留在同一行上也没关系。他们可以向上移动。

我可以想象可以删除所有具有 NA 条件(也许具有 apply)的单元格并获得结果。或者也许是一个简单的排序?

谢谢。

更新:

A   B   C
1       3
    2   
4       3

    1   2

3       5
        4
    9   
7       1
Run Code Online (Sandbox Code Playgroud)

Uwe*_*Uwe 5

OP 要求NA按列删除 s,但指出每列中可能有不同数量的 NA。

这可以通过data.table两个步骤来解决:

library(data.table)
# step 1: coerce to data.table in place, move NAs to the bottom of each column, 
# maintain the original order of non-NA values
result <- data.table(DF)[, lapply(.SD, function(x) x[order(is.na(x))])]
Run Code Online (Sandbox Code Playgroud)
     A  B  C
 1:  1  2  3
 2:  4  1  3
 3:  3  9  2
 4:  7 NA  5
 5: NA NA  4
 6: NA NA  1
 7: NA NA NA
 8: NA NA NA
 9: NA NA NA
10: NA NA NA
Run Code Online (Sandbox Code Playgroud)
# step 2: trim result
# either using Reduce
result[!result[, Reduce(`&`, lapply(.SD, is.na))]]

# or using zoo::na.trim()
zoo::na.trim(result, is.na = "all")
Run Code Online (Sandbox Code Playgroud)
    A  B C
1:  1  2 3
2:  4  1 3
3:  3  9 2
4:  7 NA 5
5: NA NA 4
6: NA NA 1
Run Code Online (Sandbox Code Playgroud)

NA因此,每列的末尾不可避免地会有一些s,因为 data.frame 中的所有列都具有相同的长度。

或者,也可以使用is.na参数 to只保留完整的行na.trim()

zoo::na.trim(result, is.na = "any")
Run Code Online (Sandbox Code Playgroud)
   A B C
1: 1 2 3
2: 4 1 3
3: 3 9 2
Run Code Online (Sandbox Code Playgroud)

替代解决方案

如前所述,data.frames 并cbind()期望所有列向量具有相同的长度。这是一个替代解决方案,如果不使用该解决方案data.table,则使用包cbind.fill()中的函数rowr,该函数用值填充向量fill直到长度相同:

setNames(do.call(function(...) rowr::cbind.fill(..., fill = NA), lapply(DF, na.omit)),
         colnames(DF))
Run Code Online (Sandbox Code Playgroud)
   A  B C
1  1  2 3
2  4  1 3
3  3  9 2
4  7 NA 5
5 NA NA 4
6 NA NA 1
Run Code Online (Sandbox Code Playgroud)

数据

正如OP在更新中提供的:

DF <- structure(list(A = c(1L, NA, 4L, NA, NA, NA, 3L, NA, NA, 7L), 
    B = c(NA, 2L, NA, NA, 1L, NA, NA, NA, 9L, NA), C = c(3L, 
    NA, 3L, NA, 2L, NA, 5L, 4L, NA, 1L)), .Names = c("A", "B", 
"C"), row.names = c(NA, -10L), class = "data.frame")
Run Code Online (Sandbox Code Playgroud)