如何在除一个向量之外的所有元素上循环函数并将结果存储在数据框的单独列中

How to loop a function over all elements of a vector except one and store the result in separate columns of a data frame

我有一个包含多列的数据框。我想 运行 函数 [在本例中为 pmax()] 遍历其名称存储在矢量中的所有列,但一个除外,并将结果存储在新的单独列中。最后,我还想将所有新列的名称存储在一个单独的向量中。一个最小的例子是:

Name <- c("Case 1", "Case 2", "Case 3", "Case 4", "Case 5")
C1 <- c(1, 0, 1, 1, 0)
C2 <- c(0, 1, 1, 1, 0)
C3 <- c(0, 1, 0, 0, 0)
C4 <- c(1, 1, 0, 1, 0)
Data <- data.frame(Name, C1, C2, C3, C4)

var.min <- function(data, col.names){
                    new.df <- data

                    # This is how I would do it outside a function and without loop:
                    new.df$max.def.col.exc.1 <- pmax(new.df$C2, new.df$C3)
                    new.df$max.def.col.exc.2 <- pmax(new.df$C1, new.df$C3)
                    new.df$max.def.col.exc.3 <- pmax(new.df$C1, new.df$C2)
                    
                    new.columns <- c("max.def.col.exc.1", "max.def.col.exc.2", "max.def.col.exc.3")

                    return(new.df)
}

new.df <- var.min(Data,
                  col.names= c("C1", "C2", "C3"))

结果应如下所示:

    Name C1 C2 C3 C4 max.def.col.exc.1 max.def.col.exc.2 max.def.col.exc.3
1 Case 1  1  0  0  1                 0                 1                 1
2 Case 2  0  1  1  1                 1                 1                 1
3 Case 3  1  1  0  0                 1                 1                 1
4 Case 4  1  1  0  1                 1                 1                 1
5 Case 5  0  0  0  0                 0                 0                 0

有人有想法吗?非常感谢!

这是 combn 的基础 R 解决方案。它获取列名的所有成对组合并调用函数计算 pmax.

请注意,预期输出列的顺序与以下代码输出的顺序相同。如果列向量是c("C1", "C2", "C3"),顺序会不同。

另请注意,该函数现在是单行函数,可以接受任意数量的列(2、3 或更多)的组合。

var.min <- function(cols, data) Reduce(pmax, data[cols])

cols <- c("C3", "C2", "C1")
combn(cols, 2, var.min, data = Data)
#     [,1] [,2] [,3]
#[1,]    0    1    1
#[2,]    1    1    1
#[3,]    1    1    1
#[4,]    1    1    1
#[5,]    0    0    0

现在只需分配列名并cbind处理输入数据。

tmp <- combn(cols, 2, var.min, data = Data)
colnames(tmp) <- paste0("max.def.col.exc.", seq_along(cols))
Data <- cbind(Data, tmp)
rm(tmp)    # final clean-up