特定数据框列上的 R Apply() 函数

Posted

技术标签:

【中文标题】特定数据框列上的 R Apply() 函数【英文标题】:R Apply() function on specific dataframe columns 【发布时间】: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], ...) 得到你得到的结果。 【参考方案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,会丢失行名或列名信息吗?

以上是关于特定数据框列上的 R Apply() 函数的主要内容,如果未能解决你的问题,请参考以下文章

如何在此数据框列的 R 中正确使用 apply?

熊猫数据框列上的子字符串

PySpark:根据另一列的顺序收集数据框列上的集合

将一些函数应用于列表中的数据框列

如何在大量数据框列上应用我的 single_space 函数? [关闭]

Pyspark - 在作为列表的 spark 数据框列上使用 reducebykey