The ConvertToLocal function below takes a data frame of Names and Times and does a timezone conversion with some if statements. How can I vectorize this so I do not use loops?
Thank you.
Here is the code:
ConvertToLocal<-function(data)
{
 Name<-data$Name
 Time<-data$Time
  for(i in 1:length(Name))
  {
    if(Name[i]== "Bob" | Name[i] == "Al"  )
    {
      Time[i]<-format(Time[i],tz="America/Los_Angeles")
    }else if (Name[i] == "Mike" | Name[i]  == "Tom" )
    {
      Time[i]<-format(Time[i],tz="Asia/Singapore")
    }else if (Name[i]  == "Fred")
    {
      Time[i]<- format(Time[i],tz="Europe/London")
    }
  }
  return(Time)
} 
Time<-c(as.POSIXct("2015-02-03 14:27:35.943", tz = "UTC"),as.POSIXct("2015-02-03 14:27:35.943", tz = "UTC"),as.POSIXct("2015-02-03 14:27:35.943", tz = "UTC"),as.POSIXct("2015-02-03 14:27:35.943", tz = "UTC"))
Name<-c("BOB","Al","Mike","Fred")
data<- data.frame(Name = Name, Time = Time)
ConvertToLocal(data)
                Loop vectorization transforms procedural loops by assigning a processing unit to each pair of operands. Programs spend most of their time within such loops. Therefore, vectorization can significantly accelerate them, especially over large data sets.
Vectorization is the process of converting an algorithm from operating on a single value at a time to operating on a set of values (vector) at one time. Modern CPUs provide direct support for vector operations where a single instruction is applied to multiple data (SIMD).
There are two ways to vectorize a loop computation in a C/C++ program. Programmers can use intrinsics inside the C/C++ source code to tell compilers to generate specific SIMD instructions so as to vectorize the loop computation. Or, compilers may be setup to vectorize the loop computation automatically.
What is Vectorization ? Vectorization is used to speed up the Python code without using loop. Using such a function can help in minimizing the running time of code efficiently.
Another approach would be to create a lookup table and then use mapply
Using data.table for ease of merging
library(data.table)
DT <- data.table(data)
TimeZones <-rbindlist(list(
  data.table(Name = c('Bob', 'Al'), tz = 'America/Los_Angeles' ),
  data.table(Name = c('Mike', 'Tom'), tz = 'Asia/Singapore'),
  data.table(Name = 'Fred', tz = 'Europe/London')
))
setkey(DT, Name)
setkey(TimeZones, Name)
final <- TimeZones[DT][, local := mapply(Time, tz = tz, FUN = format)]
final
#    Name                  tz                Time               local
# 1:   Al America/Los_Angeles 2015-02-04 01:27:35 2015-02-03 06:27:35
# 2:  Bob America/Los_Angeles 2015-02-04 01:27:35 2015-02-03 06:27:35
# 3: Fred       Europe/London 2015-02-04 01:27:35 2015-02-03 14:27:35
# 4: Mike      Asia/Singapore 2015-02-04 01:27:35 2015-02-03 22:27:35 
                        You can easily do the 3 transformations as 3 separate vectorised steps.
Time <- c(as.POSIXct("2015-02-03 14:27:35.943", tz = "UTC"),
          as.POSIXct("2015-02-03 14:27:35.943", tz = "UTC"),
          as.POSIXct("2015-02-03 14:27:35.943", tz = "UTC"),
          as.POSIXct("2015-02-03 14:27:35.943", tz = "UTC"))
Name <- c("BOB","Al","Mike","Fred")
data <- data.frame(Name = Name, Time = Time)
ConvertToLocal <- function(dat) {
  tzs <- c("America/Los_Angeles", "Asia/Singapore", "Europe/London")
  groups <- list(c("Bob", "Al"), c("Mike", "Tom"), c("Fred"))
  for (i in seq_along(groups)) {
    take <- dat$Name %in% groups[[i]]
    dat$Time[take] <- format(dat$Time[take], tz = tzs[i], usetz = TRUE)
  }
  dat
}
which gives, for the example data
> ConvertToLocal(data)
  Name                    Time
1  BOB 2015-02-03 08:27:35.943
2   Al 2015-02-03 06:27:35.943
3 Mike 2015-02-03 22:27:35.943
4 Fred 2015-02-03 14:27:35.943
                        try this:
ConvertToLocal<-function(data) {
    Name<-data$Name
    Time<-data$Time
    indx <- Name== "Bob" | Name == "Al"
    Time[indx]<-format(Time[indx],tz="America/Los_Angeles")
    indx <- Name == "Mike" | Name  == "Tom" 
    Time[indx]<-format(Time[indx],tz="Asia/Singapore")
    indx <- Name  == "Fred"
    Time[indx]<- format(Time[indx],tz="Europe/London")
    return(Time)
} 
                        Here another option , using mapply and ifelse:
  Name <- data$Name
  Time <- data$Time
  mapply(function(x,y)format(x,tz=y),Time,
         ifelse(Name %in%  c("Bob","Al"  ),
                "America/Los_Angeles",
                ifelse(Name %in%  c("Mike","Tom"  ),
                       "Asia/Singapore",
                       ifelse(Name  == "Fred","Europe/London",""))))
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With