假设我有一个数据框,其中整个列都是NA
,如下所示:
set.seed(0)
data <- data.frame(A = rnorm(10, 10, 1),
B = rnorm(10, 12, 2),
C = rep(NA, 10))
如果我在列中应用min()
,我会得到我希望的输出:
apply(data, 2, min)
# A B C
# 8.460050 9.524923 NA
但是,当我应用which.min()
时,我的输出是一个列表,而C
列是integer(0)
:
apply(data, 2, which.min)
# $A
# [1] 6
# $B
# [1] 10
# $C
# integer(0)
我可以通过这个相当丑陋的解决方法让它看起来像我想要的那样:
which.mins <- unlist(apply(data, 2, which.min))
which.mins[names(data)[!(names(data) %in% names(which.mins))]] <- NA
which.mins
# A B C
# 6 10 NA
是否有更好的方法可以模仿我在apply()
使用min()
时获得的输出?
答案 0 :(得分:6)
你说得对,如果x没有非NA,which.min
会返回0
。您仍然可以像这样使用apply
和which.min
:
apply(data, 2, function(x) {if (all(is.na(x))) {NA} else {which.min(x)} })
答案 1 :(得分:2)
请注意,在data.frame上调用apply
会导致在应用函数之前将data.frame强制转换为矩阵。您应该使用sapply
(或vapply
),否则您可能会遇到奇怪的错误,因为您的data.frame的所有列都会被强制转换为常见类型(通常是字符)。
只测试which.min
的结果长度是否为零,并在这种情况下返回NA
。
> # if() evaluates to FALSE if length(wm) is 0 because as.logical(0) is FALSE
> sapply(data, function(x) if(length(wm <- which.min(x))) wm else NA)
A B C
6 10 NA
答案 2 :(得分:0)
第一个示例没有给出NA值,因为它检测到向量中的NA并将它们作为最小值返回,它给出了NA,因为数据的C列中没有数字框架,以便它不能返回一个数字到数字向量min
的位置3返回。 which.min()
返回最小值的位置列表列表:
str(apply(data, 2, which.min)[1])
List of 1
$ A: int 6
由于C列中没有最小值,因此返回长度为0的列表,为您提供integer(0)
结果。
如果您正在尝试做什么,那么您的解决方法就可以了。或者,您可以将整个事物包装在函数
中whichMinNAs <- function(x){
if(FALSE %in% is.na(x)){
return(which.min(x))
} else {
return(NA)
}
}
apply(data, 2, whichMinNAs)
A B C
6 10 NA
答案 3 :(得分:0)
以下是一个解决方法的示例:
apply(data, 2, FUN=function(x) ifelse(length(test<-which.min(x))>0, test, NA))
> apply(data, 2, FUN=function(x) ifelse(length(test<-which.min(x))>0, test, NA))
A B C
6 10 NA