【问题标题】:R Apply() function on specific dataframe columns特定数据框列上的 R Apply() 函数
【发布时间】:2013-09-01 10:16:51
【问题描述】:

我想在数据框上使用 apply 函数,但只将该函数应用于最后 5 列。

B<- by(wifi,(wifi$Room),FUN=function(y){apply(y, 2, A)})

这将 A 应用于 y 的所有列

B<- by(wifi,(wifi$Room),FUN=function(y){apply(y[4:9], 2, A)})

这仅将 A 应用于 y 的第 4-9 列,但 B 的总回报去除了前 3 列...我仍然想要那些,我只是不想将 A 应用于它们。

wifi[,1:3]+B 

也没有做我期望/想要的。

【问题讨论】:

  • 'by' 调用使这个问题变得复杂。如果相关,您应该重写问题以澄清(什么是 wifi$Room?)。我在下面的回答中忽略了。
  • 你可以cbind(y[1:3], ...) 得到你得到的结果。

标签: r dataframe apply


【解决方案1】:

最简单的方法是使用 mutate 函数:

dataFunctionUsed <- data %>% 
  mutate(columnToUseFunctionOn = function(oldColumn ...))

【讨论】:

    【解决方案2】:

    lapply 可能是比apply 更好的选择,因为 apply 首先将您的 data.frame 强制转换为数组,这意味着所有列必须具有相同的类型。根据您的具体情况,这可能会产生意想不到的后果。

    模式是:

    df[cols] <- lapply(df[cols], FUN)
    

    “cols”向量可以是变量名或索引。我更喜欢尽可能使用名称(它对列重新排序很可靠)。所以在你的情况下,这可能是:

    wifi[4:9] <- lapply(wifi[4:9], A)
    

    使用列名的示例:

    wifi <- data.frame(A=1:4, B=runif(4), C=5:8)
    wifi[c("B", "C")] <- lapply(wifi[c("B", "C")], function(x) -1 * x)
    

    【讨论】:

    • 一个小修正:wifi
    • 您能否更明确地说明您是如何创建 [cols] 向量的?
    • @Mox 你可以做cols &lt;- c("var1", "var2")
    • 作为替代使用 dplyr 避免重复列规范的冗余,您可以这样做 wifi[4:9] %&lt;&gt;% map_dbl(A)
    • @AgileBean: map 是一个不错的选择,但我建议使用 %&lt;&gt;% 运算符。请滚动到r4ds.had.co.nz/pipes.html末尾
    【解决方案3】:

    如前所述,您只需要将标准 R apply 函数应用于列 (MARGIN=2):

    wifi[,4:9] <- apply(wifi[,4:9], MARGIN=2, FUN=A)
    

    或者,简称:

    wifi[,4:9] <- apply(wifi[,4:9], 2, A)
    

    这会使用 A() 函数就地更新 4:9 列。现在,让我们假设na.rmA() 的一个参数,它可能应该是。我们可以通过na.rm=T 从计算中删除 NA 值,如下所示:

    wifi[,4:9] <- apply(wifi[,4:9], MARGIN=2, FUN=A, na.rm=T)
    

    您想要传递给自定义函数的任何其他参数也是如此。

    【讨论】:

      【解决方案4】:

      我认为您想要的是mapply. 您可以将该函数应用于所有列,然后删除您不想要的列。但是,如果您将不同的函数应用于不同的列,您可能想要的是来自 dplyr 包的mutate

      【讨论】:

        【解决方案5】:

        使用示例 data.frame 和示例函数(对所有值 +1)

        A <- function(x) x + 1
        wifi <- data.frame(replicate(9,1:4))
        wifi
        
        #  X1 X2 X3 X4 X5 X6 X7 X8 X9
        #1  1  1  1  1  1  1  1  1  1
        #2  2  2  2  2  2  2  2  2  2
        #3  3  3  3  3  3  3  3  3  3
        #4  4  4  4  4  4  4  4  4  4
        
        data.frame(wifi[1:3], apply(wifi[4:9],2, A) )
        #or
        cbind(wifi[1:3], apply(wifi[4:9],2, A) )
        
        #  X1 X2 X3 X4 X5 X6 X7 X8 X9
        #1  1  1  1  2  2  2  2  2  2
        #2  2  2  2  3  3  3  3  3  3
        #3  3  3  3  4  4  4  4  4  4
        #4  4  4  4  5  5  5  5  5  5
        

        甚至:

        data.frame(wifi[1:3], lapply(wifi[4:9], A) )
        #or
        cbind(wifi[1:3], lapply(wifi[4:9], A) )
        
        #  X1 X2 X3 X4 X5 X6 X7 X8 X9
        #1  1  1  1  2  2  2  2  2  2
        #2  2  2  2  3  3  3  3  3  3
        #3  3  3  3  4  4  4  4  4  4
        #4  4  4  4  5  5  5  5  5  5
        

        【讨论】:

        • 有没有办法使用$ 按名称索引某个列,而不是使用[ : ] 按列号索引?我尝试添加 colnames: colnames(wifi) = c("a", "b", "c", "d", "e", "f", "g", "h" ,"i") 但没有尝试使用 lapply(wifi$e, 2, X)。
        • @skotturi - 您可以像 wifi[c("a","b","c")] 那样按名称索引多个列。
        • @thelatemail,在apply(wifi[4:9],2, A),wifi[4:9]data.frame。而apply只能用于数组或矩阵。为什么你的答案可行?
        • @kittygirl - 这是因为 apply 可以 用于 data.frame。使用 apply 时,data.frame 将作为函数的一部分强制转换为矩阵。
        • @thelatemail,会丢失行名或列名信息吗?
        猜你喜欢
        • 1970-01-01
        • 2013-04-18
        • 2021-04-05
        • 1970-01-01
        • 2012-03-26
        • 1970-01-01
        • 2017-07-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多