我刚刚读了@David的简介,发现了一些有用的技巧来培养良好的R-编程技能/习惯,其中一条特别让我印象深刻。我一直认为R中的应用函数是使用dataframes的基石,但他写道:
如果您正在使用data.frames,请忘记有一个名为apply的函数--不管您做什么--不要使用它。特别是在边距为1的情况下(这个函数的唯一好用法是对矩阵列进行操作-边距为2)。 一些很好的选择:?do.call,?pmax/pmin,?max.col,?rowSums/rowMeans/等,令人敬畏的matrixStats包(用于矩阵),?rowsum等等。
有人能给我解释一下吗?为什么应用函数不受欢迎?
发布于 2018-06-06 11:29:00
apply(DF, 1, f)将每一行DF转换为向量,然后将该向量传递给f。如果DF是字符串和数字的混合,那么该行在传递给f之前将被转换为字符向量,这样即使行iris[i, -5]包含所有数字元素,apply(iris, 1, function(x) sum(x[-5]))也无法工作。行被转换为字符串,您不能对字符串进行求和。另一方面,apply(iris[-5], 1, sum)将与rowSums(iris[-5])一样工作。f生成一个向量,则结果是一个矩阵,而不是另一个数据帧;而且,结果是您可能期望的结果的转换。这
申请(BOD,1,身份)
给出以下内容,而不是返回BOD:
、1、3、5次1.0 2.0 3 4 5.0 7.0需求8.3 10.3 19 16
许多年前,哈德利韦翰( Hadley Wickham )做了帖子 iapply,它是幂等的,意思是iapply(mat, 1, identity)返回mat,而不是t(mat) ( mat是矩阵)。最近,用他的plyr软件包,人们可以写:
图书馆(Plyr) ddplyr(BOD,1,标识)
并将BOD作为数据框架返回。另一方面,apply(BOD, 1, sum)将给出与rowSums(BOD)和apply(BOD, 1, f)相同的结果,对于函数f可能有用,对于f生成标量,并且没有对应的结果,例如sum / rowSums情况。另外,如果f生成一个向量,并且您不介意矩阵结果,那么您可以自己转换apply的输出,尽管效果很差。
发布于 2018-06-06 09:58:56
我认为作者的意思是,如果可以并且避免应用(因为原则上它是一个for循环并花费更长的时间),那么您应该使用预构建/向量化函数(因为它更容易):
library(microbenchmark)
d <- data.frame(a = rnorm(10, 10, 1),
b = rnorm(10, 200, 1))
# bad - loop
microbenchmark(apply(d, 1, function(x) if (x[1] < x[2]) x[1] else x[2]))
# good - vectorized but same result
microbenchmark(pmin(d[[1]], d[[2]])) # use double brackets!
# edited:
# -------
# bad: lapply
microbenchmark(data.frame(lapply(d, round, 1)))
# good: do.call faster than lapply
microbenchmark(do.call("round", list(d, digits = 1)))
# --------------
# Unit: microseconds
# expr min lq mean median uq max neval
# do.call("round", list(d, digits = 1)) 104.422 107.1 148.3419 134.767 184.524 332.009 100
# expr min lq mean median uq max neval
# data.frame(lapply(d, round, 1)) 235.619 243.2055 298.5042 252.353 276.004 1550.265 100
#
# expr min lq mean median uq max neval
# do.call("round", list(d, digits = 1)) 96.389 97.5055 113.075 98.175 105.5375 730.954 100
# expr min lq mean median uq max neval
# data.frame(lapply(d, round, 1)) 235.619 243.2055 298.5042 252.353 276.004 1550.265 100发布于 2018-06-06 11:51:48
它与R存储矩阵和数据帧的方式有关。您可能知道,data.frame是向量的list,也就是说,data.frame中的每一列都是向量。作为一种矢量化语言,最好是对向量进行操作,这就是为什么apply的边距为2被拒绝的原因:这样做,您将不会在向量上工作,而是在每次迭代中跨越不同的向量。
据我所知,使用带边距1的apply与使用do.call没有太大的不同。虽然后者可能允许一些更多的使用灵活性。
*这些信息应该在手册的某个地方。
https://stackoverflow.com/questions/50717040
复制相似问题