I have a quite large data frame, about 10 millions of rows. It has columns x
and y
, and what I want is to compute
hypot <- function(x) {sqrt(x[1]^2 + x[2]^2)}
for each row. Using apply
it would take a lot of time (about 5 minutes, interpolating from lower sizes) and memory.
But it seems to be too much for me, so I've tried different things:
- compiling the
hypot
function reduces the time by about 10% - using functions from
plyr
greatly increases the running time.
What's the fastest way to do this thing?
While Ben Bolkers answer is comprehensive, I will explain other reasons to avoid
apply
on data.frames.apply
will convert yourdata.frame
to a matrix. This will create a copy (waste of time and memory), as well as perhaps causing unintended type conversions.Given that you have 10 million rows of data, I would suggest you look at the
data.table
package that will let you do things efficiently in terms of memory and time.For example, using
tracemem
This is even worse if you then assign to a column in
d
4 copies! -- with 10 million rows, that will probably come and bite you at somepoint.
If we use
with
, there is nocopying
involved, if we assign to a vectorBut there will be if we assign to a column in the data.frame
d
Now, if you use
data.table
and:=
to assign by reference (no copying)No copies!
Perhaps I will be corrected here, but another memory issue to consider is that
sqrt(x^2+y^2))
will create 4 temporary variables (internally)x^2
,y^2
,x^2 + y^2
and thensqrt(x^2 + y^2))
The following will be slower, but only involve two variables being created.
R is vectorised, so you could use the following, plugging in your own matrix of course
Nice and efficient :)
What about
with(my_data,sqrt(x^2+y^2))
?Two different per-line functions, one taking advantage of vectorization:
Try compiling these too:
Results:
As expected the
with()
solution and the column-indexing solution à la Tyler Rinker are essentially identical;hypot2
is twice as fast as the originalhypot
(but still about 150 times slower than the vectorized solutions). As already pointed out by the OP, compilation doesn't help very much.