如何向量化这个循环

时间:2015-02-03 23:58:24

标签: r

下面的ConvertToLocal函数采用NamesTimes的数据框,并使用一些if语句进行时区转换。我如何对此进行矢量化,以便不使用循环?

谢谢。

以下是代码:

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)

4 个答案:

答案 0 :(得分:4)

另一种方法是创建一个查找表,然后使用mapply

使用data.table以便于合并

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 

答案 1 :(得分:3)

您可以轻松地将3个转换作为3个单独的矢量化步骤。

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
}

给出了示例数据

> 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

答案 2 :(得分:2)

试试这个:

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)
} 

答案 3 :(得分:1)

这是另一种选择,使用mapplyifelse

  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",""))))