不同 data.frame 修改操作之间的效率差异
Efficiency discrepancies between different data.frame modification operations
我观察到 R 中 data.frame 修改的效率存在以下差异:
microbenchmark::microbenchmark(
mtcars$mpg[1] <- 0,
mtcars[["mpg"]][1] <- 0,
mtcars[1,"mpg"] <- 0
)
Unit: microseconds
expr min lq mean median uq max neval
mtcars$mpg[1] <- 0 4.400 4.801 5.16010 5.0020 5.3005 14.001 100
mtcars[["mpg"]][1] <- 0 9.600 10.201 11.08797 10.5010 10.8015 61.001 100
mtcars[1, "mpg"] <- 0 12.702 13.451 14.28102 13.8015 14.1020 47.701 100
此外,使用 $
的第一种方法似乎比 [[
和 [
扩展得更好,后者似乎在线性时间内工作。
f <- function(nrow){
df <- mtcars[sample(1:32,nrow,TRUE), ]
microbenchmark::microbenchmark(
df$mpg[1] <- 0,
df[["mpg"]][1] <- 0,
df[1,"mpg"] <- 0
)
}
> f(1e5)
Unit: microseconds
expr min lq mean median uq max neval
df$mpg[1] <- 0 4.801 5.7505 41.92301 6.5505 12.2515 253.501 100
df[["mpg"]][1] <- 0 140.401 146.4510 162.82191 154.8005 165.3005 267.400 100
df[1, "mpg"] <- 0 144.801 151.5005 167.17197 159.9010 171.7010 277.102 100
> f(1e6)
Unit: microseconds
expr min lq mean median uq max neval
df$mpg[1] <- 0 5.601 10.551 733.995 18.251 918.6015 36519.5 100
df[["mpg"]][1] <- 0 908.402 1013.052 2420.035 1278.751 1704.5505 52940.7 100
df[1, "mpg"] <- 0 846.401 1018.101 2356.817 1332.900 1628.1510 57710.4 100
是什么导致了这种行为?我读过的大多数 R 文本似乎都将 mtcars$mpg
和 mtcars[["mpg"]]
视为可互换的,因此它们修改不同的事实非常令人困惑。
编辑:我 运行 基于下面 Karolis 的回答的快速基准测试。方法 [[.data.frame
似乎是罪魁祸首。如果将 data.frame
强制转换为 list
.
,则性能具有可比性
> mtlist <- as.list(mtcars)
> microbenchmark::microbenchmark(
+ mtlist$mpg[1] <- 1,
+ mtlist[["mpg"]][1] <- 1
+ )
Unit: nanoseconds
expr min lq mean median uq max neval
mtlist$mpg[1] <- 1 801 900 1045.96 901 1051.0 5501 100
mtlist[["mpg"]][1] <- 1 701 801 1191.16 851 951.5 19401 100
没有 $.data.frame
运算符 - 因此使用列表的 $
代替。
`$.data.frame`
Error: object '$.data.frame' not found
虽然[.data.frame
和[[.data.frame
都是用R代码实现的函数。
`[.data.frame`
function...
`[[.data.frame`
function...
您还可以在 help('[.data.frame')
中阅读相关内容:
> [...] There is no ‘data.frame’ method for ‘$’, so ‘x$name’ uses the
default method which treats ‘x’ as a list [...]
我观察到 R 中 data.frame 修改的效率存在以下差异:
microbenchmark::microbenchmark(
mtcars$mpg[1] <- 0,
mtcars[["mpg"]][1] <- 0,
mtcars[1,"mpg"] <- 0
)
Unit: microseconds
expr min lq mean median uq max neval
mtcars$mpg[1] <- 0 4.400 4.801 5.16010 5.0020 5.3005 14.001 100
mtcars[["mpg"]][1] <- 0 9.600 10.201 11.08797 10.5010 10.8015 61.001 100
mtcars[1, "mpg"] <- 0 12.702 13.451 14.28102 13.8015 14.1020 47.701 100
此外,使用 $
的第一种方法似乎比 [[
和 [
扩展得更好,后者似乎在线性时间内工作。
f <- function(nrow){
df <- mtcars[sample(1:32,nrow,TRUE), ]
microbenchmark::microbenchmark(
df$mpg[1] <- 0,
df[["mpg"]][1] <- 0,
df[1,"mpg"] <- 0
)
}
> f(1e5)
Unit: microseconds
expr min lq mean median uq max neval
df$mpg[1] <- 0 4.801 5.7505 41.92301 6.5505 12.2515 253.501 100
df[["mpg"]][1] <- 0 140.401 146.4510 162.82191 154.8005 165.3005 267.400 100
df[1, "mpg"] <- 0 144.801 151.5005 167.17197 159.9010 171.7010 277.102 100
> f(1e6)
Unit: microseconds
expr min lq mean median uq max neval
df$mpg[1] <- 0 5.601 10.551 733.995 18.251 918.6015 36519.5 100
df[["mpg"]][1] <- 0 908.402 1013.052 2420.035 1278.751 1704.5505 52940.7 100
df[1, "mpg"] <- 0 846.401 1018.101 2356.817 1332.900 1628.1510 57710.4 100
是什么导致了这种行为?我读过的大多数 R 文本似乎都将 mtcars$mpg
和 mtcars[["mpg"]]
视为可互换的,因此它们修改不同的事实非常令人困惑。
编辑:我 运行 基于下面 Karolis 的回答的快速基准测试。方法 [[.data.frame
似乎是罪魁祸首。如果将 data.frame
强制转换为 list
.
> mtlist <- as.list(mtcars)
> microbenchmark::microbenchmark(
+ mtlist$mpg[1] <- 1,
+ mtlist[["mpg"]][1] <- 1
+ )
Unit: nanoseconds
expr min lq mean median uq max neval
mtlist$mpg[1] <- 1 801 900 1045.96 901 1051.0 5501 100
mtlist[["mpg"]][1] <- 1 701 801 1191.16 851 951.5 19401 100
没有 $.data.frame
运算符 - 因此使用列表的 $
代替。
`$.data.frame`
Error: object '$.data.frame' not found
虽然[.data.frame
和[[.data.frame
都是用R代码实现的函数。
`[.data.frame`
function...
`[[.data.frame`
function...
您还可以在 help('[.data.frame')
中阅读相关内容:
> [...] There is no ‘data.frame’ method for ‘$’, so ‘x$name’ uses the
default method which treats ‘x’ as a list [...]