特定数据框列上的 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 <- c("var1", "var2")
作为替代使用 dplyr 避免重复列规范的冗余,您可以这样做 wifi[4:9] %<>% map_dbl(A)
@AgileBean: map
是一个不错的选择,但我建议使用 %<>%
运算符。请滚动到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.rm
是A()
的一个参数,它可能应该是。我们可以通过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() 函数的主要内容,如果未能解决你的问题,请参考以下文章