[R] Fastest way to repeatedly subset a data frame?
Iestyn Lewis
ilewis at pharm.emory.edu
Fri Apr 20 21:07:09 CEST 2007
That is a seriously neat bit of code there. (I'm new to non-loop-based
programming, forgive my enthusiasm).
But... it's not any faster, which is worrisome to me because it seems
like your code uses rownames and would take advantage of the hashing
potential of named items.
I'm currently looking at converting the vectors of ids to lists. I've
also come across some pages which make reference to a setting up a new
environment using the hash=TRUE argument, but it's unclear to me on how
you go about using that new environment.
Thanks,
Iestyn
hadley wickham wrote:
> On 4/20/07, Iestyn Lewis <ilewis at pharm.emory.edu> wrote:
>> Hi -
>>
>> I have a data frame with a large number of observations (62,000 rows,
>> but only 2 columns - a character ID and a result list).
>>
>> Sample:
>>
>> > my.df <- data.frame(id=c("ID1", "ID2", "ID3"), result=1:3)
>> > my.df
>> id result
>> 1 ID1 1
>> 2 ID2 2
>> 3 ID3 3
>>
>> I have a list of ID vectors. This list will have anywhere from 100 to
>> 1000 members, and each member will have anywhere from 10 to 5000 id
>> entries.
>>
>> Sample:
>>
>> > my.idlist[["List1"]] <- c("ID1", "ID3")
>> > my.idlist[["List2"]] <- c("ID2")
>> > my.idlist
>> $List1
>> [1] "ID1" "ID3"
>>
>> $List2
>> [1] "ID2"
>>
>>
>> I need to subset that data frame by the list of IDs in each vector, to
>> end up with vectors that contain just the results for the IDs found in
>> each vector in the list. My current approach is to create new columns
>> in the original data frame with the names of the list items, and any
>> results that don't match replaced with NA. Here is what I've done so
>> far:
>>
>> createSubsets <- function(res, slib) {
>> for(i in 1:length(slib)) {
>> res[ ,names(slib)[i]] <- replace(res$result,
>> which(!is.element(res$sid, slib[[i]])), NA)
>> return (res)
>> }
>> }
>>
>> I have 2 problems:
>>
>> 1) My function only works for the first item in the list:
>>
>> > my.df <- createSubsets(my.df, my.idlist)
>> > my.df
>> id result List1
>> 1 ID1 1 1
>> 2 ID2 2 NA
>> 3 ID3 3 3
>>
>> In order to get all results, I have to copy the loop out of the function
>> and paste it into R directly.
>>
>> 2) It is very, very slow. For a dataset of 62,000 rows and 253 list
>> entries, it takes probably 5 minutes on a pentium D. An implementation
>> of this kind of subsetting using hashtables in C# takes a neglible
>> amount of time.
>>
>> I am open to any suggestions about data format, methods, anything.
>
> How about:
>
> df <- data.frame(id=c("ID1", "ID2", "ID3"), result=1:3)
>
> ids <- list()
> ids[["List1"]] <- c("ID1", "ID3")
> ids[["List2"]] <- c("ID2")
>
> rownames(df) <- df$id
> lapply(ids, function(id) df[id, ])
>
> Hadley
More information about the R-help
mailing list