You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[R-Forge #1705] Change CJ internally not to expand, for efficiency #652
Submitted by: Matt Dowle; Assigned to: Nobody; R-Forge link
CJ() could return an irregular column length data.table (its inputs unchanged), marked somehow so that binarysearch knows to %% index through the CJ columns, rather than allocating long vectors and populating them as CJ currently does. Purely for speed, with no changes for users unless perhaps CJ() has been used outside [.data.table.
Or, more generally, data.table columns could be marked so that indexing to them knows they should be recycled, without actually allocating and recycling the columns. Discuss on datatable-help needed as under-the-hood code e.g. DT$foo[903] might not work if it was internally a short vector. In reality it's probably only useful for CJ() as regular data.table's only have recycled data perhaps to start with creating them with say an NA column but then are quickly populated. If a large table has a column with the same value (say NA or 0) for every row, perhaps the column is redundant. Can't imagine that recycling >1 items is often useful (other than in CJ()).
Yes please. Maybe some non standard evaluation hacking in [.data.table is enough.
I guess you should decide how far you want to go with optimizing i (I am thinking of | and &)..If not very far very soon, I would really want to have a way to x[y, on=c("a"=b)] retaining the key of x( see #1268), such that the concerned user can achieve high performance easily in an imperative way.
best,Jan
@jan-glx I'm confused - what exactly are you trying to demonstrate? I didn't run your code, but you show that the result of your two functions is not identical, then you talk about a speedup...
Fwiw I would want to see a different function if this idea gets implemented, and not a drastic change to what CJ does - as I use it the other way around all the time - CJ(...)[...].
Hm, are you just asking that autoindexing be extended? Seems like the clearest demonstration is just
r <- dt[x %in% sort(unique(goodX))][y %in% sort(unique(goodY))] # just as fast as rDJ
identical(r,rDJ) # TRUE
(All of your setattr sort of cloud what's going on to me, not to mention the nomatch=0 which should have no effect in fNJ.) Anyway, I agree that further optimization for fNJ would be nice, as would some convenient shortcut, like DT[list(x=goodX, y=goodY, z=goodZ), on=.ALLIN]
Kinda, yes. I would prefer to to describe what I want instead of heaving to explicitly say want R to do. However current optimization only works for some (through the most important) cases. And I am afraid it is supporting the use of data.table in a not data.table way leading to problems as soon as optimization does not kick in. E.g. see:
> library(data.table)
> dt = data.table(x = sample(1E5, 1E8, replace=T))
> setkey(dt,x,verbose=T)
forder took 2.47 sec
reorder took 2.16 sec
> system.time(dt[.(42),])
user system elapsed
0 0 0
> system.time(dt[x==42,])
user system elapsed
0 0 0
> system.time(dt[42==x,])
user system elapsed
0.72 0.38 1.09
> system.time(dt[x %in% 42,])
user system elapsed
0 0 0
> system.time(dt[x %in% 42 & TRUE,])
user system elapsed
4.38 0.54 4.92
But I am not sure what I want or what the best solution would be...an how much of it concerns this issue...
Expressing the WHERE ... AND ... as CJ felt fine for me (apart from the fact that it expands and is terrible slow (for a dt command))... A real query language for i would be cool (one that warns you if it cannot be optimized to joins)
Alternatively if one could do joins that preserve the keys or if data.table would automatically create and keep if easily possible indices like in what @jangorecki seems to be implementing That would be awesome as well.
PS: In your %in% query: Why is the key preserved (only) if both good arrays are sorted?
Regarding multiple indexes you've linked, it quite heavy implementation as it stores not just integer order sequence for each index but all the column values included in the index for each index, see idxv.R#L10. I'm not sure if this what you discuss here fits to the first post which is clearly focused on single change for CJ.
I wouldn't go that way unless there will be officially documented (at least on r-devel mailing) ALTREP api to represent cross product of data.frames, otherwise such API is likely to change without any notice.
Activity
jan-glx commentedon Sep 10, 2015
Yes please. Maybe some non standard evaluation hacking in
[.data.tableis enough.I guess you should decide how far you want to go with optimizing
i(I am thinking of | and &)..If not very far very soon, I would really want to have a way to x[y, on=c("a"=b)] retaining the key of x( see #1268), such that the concerned user can achieve high performance easily in an imperative way.best,Jan
see for example this >50x speedup:
EDIT: Ah sry, before posting I did some further "optimization" and didn't notice it produced wrong results with it. My point now holds hopefully:)
eantonya commentedon Sep 10, 2015
@jan-glx I'm confused - what exactly are you trying to demonstrate? I didn't run your code, but you show that the result of your two functions is not identical, then you talk about a speedup...
Fwiw I would want to see a different function if this idea gets implemented, and not a drastic change to what
CJdoes - as I use it the other way around all the time -CJ(...)[...].jan-glx commentedon Sep 10, 2015
Here is the example with the "optimization" on again. And another direct implementation that might make clearer when this is useful.
franknarf1 commentedon Sep 10, 2015
Hm, are you just asking that autoindexing be extended? Seems like the clearest demonstration is just
(All of your
setattrsort of cloud what's going on to me, not to mention thenomatch=0which should have no effect infNJ.) Anyway, I agree that further optimization forfNJwould be nice, as would some convenient shortcut, likeDT[list(x=goodX, y=goodY, z=goodZ), on=.ALLIN]jan-glx commentedon Sep 11, 2015
Kinda, yes. I would prefer to to describe what I want instead of heaving to explicitly say want R to do. However current optimization only works for some (through the most important) cases. And I am afraid it is supporting the use of data.table in a not data.table way leading to problems as soon as optimization does not kick in. E.g. see:
But I am not sure what I want or what the best solution would be...an how much of it concerns this issue...
Expressing the WHERE ... AND ... as CJ felt fine for me (apart from the fact that it expands and is terrible slow (for a dt command))... A real query language for i would be cool (one that warns you if it cannot be optimized to joins)
Alternatively if one could do joins that preserve the keys or if data.table would automatically create and keep if easily possible indices like in what @jangorecki seems to be implementing That would be awesome as well.
PS: In your %in% query: Why is the key preserved (only) if both good arrays are sorted?
jangorecki commentedon Sep 11, 2015
Regarding multiple indexes you've linked, it quite heavy implementation as it stores not just integer order sequence for each index but all the column values included in the index for each index, see idxv.R#L10. I'm not sure if this what you discuss here fits to the first post which is clearly focused on single change for CJ.
MichaelChirico commentedon Oct 11, 2018
where does this stand now that R has
ALTREP?jan-glx commentedon Oct 11, 2018
If the following version includes
ALTREPthen the room for improvement is still present.jangorecki commentedon Oct 12, 2018
I wouldn't go that way unless there will be officially documented (at least on r-devel mailing) ALTREP api to represent cross product of data.frames, otherwise such API is likely to change without any notice.
MichaelChirico commentedon Apr 14, 2024
I think it could be our own ALTREP class, though I still don't find good documentation on how to use ALTREP, exactly :)