0
\$\begingroup\$

This R code separates the values in rData. They are classified according to the class in rClass.

To do that, ClassifiedrData is a named list, where each element in the list (a class), should be a vector with all the elements in that class.

It is slow, and I had read that I should not use for in R, but I have no clue on how to vectorize it.

(I do not necessarily need a dictionary, so I welcome another data structure to store the classified numbers if it is more practical.)

I made random data (rData and rClass) as an example, but my real data is not random (so I simply creating the data classified is not a solution)

CreateEmptyDictionary <- function(names) {
    mylist.names <- names
    mylist <- vector("list", length(mylist.names))
    names(mylist) <- mylist.names
    return(mylist)
}


#Random integers
rData <- sample(x = as.integer(c(1:100)), size = 100)

#Random class  
rClass <- sample(x = c(1:10), size = 100, replace = TRUE)

#Separate rData according to his class in rClass
i <- 0
ClassifiedrData <- CreateEmptyDictionary(names <- sort(unique(rClass)))

for (a in rData) {
    i <- i + 1
    #ClassifiedrData[[rClass[i]]] <-  append(ClassifiedrData[[rClass[i]]], a)
    ClassifiedrData[[rClass[i]]][length(ClassifiedrData[[rClass[i]]])+1] <- a
}
\$\endgroup\$
  • \$\begingroup\$ Welcome to Code Review! What task does this code accomplish? Please tell us, and also make that the title of the question via edit. Maybe you missed the placeholder on the title element: "State the task that your code accomplishes. Make your title distinctive.". Also from How to Ask: "State what your code does in your title, not your main concerns about it.". \$\endgroup\$ – Sᴀᴍ Onᴇᴌᴀ Apr 10 '18 at 15:56
1
\$\begingroup\$

This is actually a 1-liner with the built-in split function:

ClassifiedrDataSplit <- split(rData, rClass)

You can confirm this returns the same result as your original code:

identical(ClassifiedrData, ClassifiedrDataSplit)
# [1] TRUE

In addition to being a lot less code, this will result in sensible speedups for larger datasets. For instance, consider the performance with 10 million elements and 10 classes:

rData <- sample(x = as.integer(c(1:1e7)), size = 1e7)
rClass <- sample(x = c(1:10), size = 1e7, replace = TRUE)
system.time({i <- 0
ClassifiedrData <- CreateEmptyDictionary(names <- sort(unique(rClass)))

for (a in rData) {
    i <- i + 1
    #ClassifiedrData[[rClass[i]]] <-  append(ClassifiedrData[[rClass[i]]], a)
    ClassifiedrData[[rClass[i]]][length(ClassifiedrData[[rClass[i]]])+1] <- a
}})
#    user  system elapsed 
#   5.248   0.435   5.749 
system.time(split(rData, rClass))
#    user  system elapsed 
#   0.258   0.083   0.357 

The solution with split is about 10x faster.

\$\endgroup\$
  • \$\begingroup\$ Wow! How do you find the right function. Do you have the entire libraries in your head? \$\endgroup\$ – zexot Apr 10 '18 at 15:27
  • \$\begingroup\$ Thank you. Have a prize youtube.com/watch?v=fD7ji3YOwcM \$\endgroup\$ – zexot Apr 10 '18 at 15:29
  • \$\begingroup\$ @zexot Unfortunately R has a huge number of these special-purpose functions that you just need to know or you spend a lot of time reinventing the wheel. I guess through time you pick up the ones that have come in handy a few times. \$\endgroup\$ – josliber Apr 10 '18 at 15:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.