【问题标题】:Apply a function to each column of a data.frame and organize the output将函数应用于 data.frame 的每一列并组织输出
【发布时间】:2019-05-09 08:40:51
【问题描述】:

我有这个向量:

 x <- c(5,2,-4,-6,-2,1,4,2,-3,-6,-1,8,9,5,-6,-11)

我使用这个功能:

myfunction <- function(x){
     n <- length(x)
     fx <- numeric(n)
     fx[1] <- min(x[1],0)
     for(i in 2:n){fx[i] <- min(0,fx[i-1]+x[i])}
     fx

     x_min <-min(x)
     fx_min <- min(fx)

     fx_05 <- numeric(n)
     fx_05[1] <- min(fx[1],0)
     for (i in 2:n) {
       if (sum(fx_05[i-1]+x[i])>0) {  
          fx_05[i] <- 0
       } else if ((sum(fx_05[i-1]+x[i]))<(fx_min*0.5)) {
          fx_05[i] <- (fx_min*0.5)
       } else { fx_05[i] <- sum(fx_05[i-1]+x[i]) }
     }
     fx_05
     as.data.frame(matrix(c(x, fx_05), ncol = 2 ))
}
xx <- myfunction(x)

数据框xx

    V1   V2
1    5  0.0
2    2  0.0
3   -4 -4.0
4   -6 -8.5
5   -2 -8.s
6    1 -7.5
7    4 -3.5
8    2 -1.5
9   -3 -4.5
10  -6 -8.5
11  -1 -8.5
12   8 -0.5
13   9  0.0
14   5  0.0
15  -6 -6.0
16 -11 -8.5`

我想将此函数应用于 data.frame :

df <- data.frame(x <- c(5,2,-4,-6,-2,1,4,2,-3,-6,-1,8,9,5,-6,-11),
                   y <- c(5,2,-4,-6,-2,1,4,2,-3,-6,-1,8,9,5,-6,-11),
                   z <- c(5,2,-4,-6,-2,1,4,2,-3,-6,-1,8,9,5,-6,-11))

使用:

output <- myfunction(df) 

它不起作用,并且正在使用:

outputs <- data.frame(sapply(df, myfunction))

data.frame 输出的格式不正确。 data.frame 的每个原始列应该是 2 列。

【问题讨论】:

    标签: r function dataframe apply sapply


    【解决方案1】:

    在这种情况下,您想使用lapply。它将处理 data.frame 的每一列,因为它实际上是一个等长向量的列表,并且每个返回一个两列 data.frame。

    x <- lapply(df, myfunction)
    

    另外,sapply 工作得很好。唯一的区别是它在开始时看起来不同。有关所有解决方案之间的区别,请参阅print(x)

    x <- sapply(df, myfunction)
    

    之后,您可能希望再次将它们从列表组合到 data.frame。你可以用do.call来做到这一点

    df2 <- do.call(cbind, x)
    

    这会弄乱列名。您可以使用 names 更改这些内容

    names(df2) <- NULL
    df2
    # 1    5  0.0   5  0.0   5  0.0
    # 2    2  0.0   2  0.0   2  0.0
    # 3   -4 -4.0  -4 -4.0  -4 -4.0
    # 4   -6 -8.5  -6 -8.5  -6 -8.5
    # ....
    

    旁注:

    如果您没有 data.frame 而是一个矩阵作为输入,另一个选项是 applyMARGIN = 2

    x <- apply(df, MARGIN = 2, myfunction)
    

    虽然在这个例子中,它也可以工作,但是当你的向量中有不同的数据类型时,你会遇到麻烦,因为它会在应用函数之前将 data.frame 转换为矩阵。因此不推荐。更多信息可以在this detailed and easy-to-understand post找到!

    进一步阅读:
    Hadley Wickham's Advanced R。另请查看本网站上有关数据类型的部分。
    Peter Werner's blog post


    我非常感谢@Gregor 在这篇文章中的投入。

    【讨论】:

    • 请不要将lapplysapply 等同于apply(..., MARGIN = 2)apply 用于矩阵,应在适当时使用。当数据框需要apply(df, MARGIN = 2) 时,我一直在努力思考这种情况,几乎总是应该使用lapplysapply
    • 我理解您的担忧。您希望将其从答案中删除,还是将其标记为一种可能但不方便的解决方案?我只是将它包含在内,因为它会导致所需的输出。
    • 如果这是我的答案,我会删除它。很好很简单。更好的是把它移到底部并解释。类似“如果你有一个矩阵,而不是数据框,请使用apply。可以在数据框上使用apply,但它会首先将数据框转换为matrix,如果你这样做是有风险的有不同类型的列,所以如果你有一个数据框,最好只使用l/s/vapply。”但更详细。也许链接到this excellent answer 以获取更多信息。
    猜你喜欢
    • 1970-01-01
    • 2015-02-23
    • 2018-07-17
    • 2013-01-27
    • 2011-12-28
    • 2015-07-12
    • 2020-12-09
    • 2014-09-05
    • 1970-01-01
    相关资源
    最近更新 更多