我试图在我的程序中使用 pmax 函数。我有一个数字数据框,我试图将它与单个数字进行比较。输出有NA。

我发现数据框不适用于 pmax,所以我将数据框更改为矩阵。它奏效了。我很好奇为什么数据框返回 NA。和回收有关系吗?

代码:-

mat <- matrix(runif(500), nrow = 20, ncol = 5)
df <- as.data.frame(mat)


pmax(mat, .5) # No NA's

pmax(df, .5) # Many NA's

最佳答案

这是第二个参数上的值的复制没有完全回收的问题之一,即它取决于列数。这可能是原因

rep(0.5, ncol(df))[df < 0.5]
#[1] 0.5 0.5  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
#[41]  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA

请注意,对于前 2 个值,0.5 正在正确更改,因为这些元素 df < 0.5 的逻辑矩阵为 TRUE,而事实并非如此,因为 0.5 仅根据列数进行复制。

假设,我们看 pmax ,这一行
mmm[change] <- each[change]

是有问题的。我们可以通过 print 'each' 和 'each[change] 的输出来检查输出。如果我们修改函数以包含 print 语句
pmax2 <- function (..., na.rm = FALSE)
{
    elts <- list(...)
    if (length(elts) == 0L)
        stop("no arguments")
    if (all(vapply(elts, function(x) is.atomic(x) && !is.object(x),
        NA))) {
        mmm <- .Internal(pmax(na.rm, ...))
        mostattributes(mmm) <- attributes(elts[[1L]])
    }
    else {
        mmm <- elts[[1L]]
        has.na <- FALSE
        as <- methods::as
        asL <- function(x) if (isS4(x))
            as(x, "logical")
        else x
        for (each in elts[-1L]) {
            l1 <- length(each)
            l2 <- length(mmm)
            if (l2 && (l2 < l1 || !l1)) {
                if (l1%%l2)
                  warning("an argument will be fractionally recycled")
                mmm <- rep(mmm, length.out = l1)
            }
            else if (l1 && (l1 < l2 || !l2)) {
                if (l2%%l1)
                  warning("an argument will be fractionally recycled")
                each <- rep(each, length.out = l2)
            }
            na.m <- is.na(mmm)
            na.e <- is.na(each)
            if (has.na || (has.na <- any(na.m) || any(na.e))) {
                if (any(na.m <- asL(na.m)))
                  mmm[na.m] <- each[na.m]
                if (any(na.e <- asL(na.e)))
                  each[na.e] <- mmm[na.e]
            }
            nS4 <- !isS4(mmm)
            if (isS4(change <- mmm < each) && (nS4 || !isS4(each)))
                change <- as(change, "logical")
            change <- change & !is.na(change)
            print(change)
            mmm[change] <- each[change]
            print(each)
            print(each[change])
            if (has.na && !na.rm)
                mmm[na.m | na.e] <- NA
            if (nS4)
                mostattributes(mmm) <- attributes(elts[[1L]])
        }
    }
    mmm
}

现在,我们根据在 'df' 上应用 print 来检查 pmax2 输出
invisible(pmax2(df, 0.5))
#       V1    V2    V3    V4    V5
# [1,]  TRUE  TRUE  TRUE  TRUE FALSE
# [2,]  TRUE FALSE  TRUE  TRUE  TRUE
# [3,] FALSE FALSE  TRUE  TRUE FALSE
# [4,] FALSE  TRUE  TRUE  TRUE  TRUE
# [5,] FALSE  TRUE  TRUE FALSE  TRUE
# [6,] FALSE FALSE  TRUE  TRUE  TRUE
# [7,]  TRUE  TRUE  TRUE FALSE  TRUE
# [8,] FALSE FALSE  TRUE FALSE FALSE
# [9,] FALSE FALSE  TRUE FALSE  TRUE
#[10,]  TRUE  TRUE  TRUE  TRUE FALSE
#[11,] FALSE  TRUE  TRUE  TRUE  TRUE
#[12,]  TRUE  TRUE FALSE  TRUE FALSE
#[13,] FALSE  TRUE  TRUE  TRUE FALSE
#[14,] FALSE  TRUE FALSE FALSE  TRUE
#[15,]  TRUE FALSE FALSE FALSE  TRUE
#[16,] FALSE  TRUE FALSE  TRUE FALSE
#[17,]  TRUE FALSE  TRUE FALSE FALSE
#[18,]  TRUE FALSE  TRUE FALSE  TRUE
#[19,] FALSE FALSE  TRUE  TRUE  TRUE
#[20,]  TRUE FALSE  TRUE FALSE  TRUE
#[1] 0.5 0.5 0.5 0.5 0.5
# [1] 0.5 0.5  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
#[41]  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA

请注意,这与我们使用前面提到的 rep 获得的输出完全相同。

但是,在 matrix 上,由于 if/else 语句,这不会执行
invisible(pmax2(mat, 0.5))

什么都没有打印

与单个元素相比,在 pmax 上应用 matrix 比在 data.frame 和该元素上应用更好。否则,我们可以 unlist data.frame 或将其转换为 matrix
all.equal(c(pmax(mat, .5)), pmax(unlist(df), .5), check.attributes = FALSE)
#[1] TRUE

数据
set.seed(24)
mat <- matrix(runif(500), nrow = 20, ncol = 5)
df <- as.data.frame(mat)

关于R 编程 - 带数据框的 pmax,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47493384/

10-12 23:35