【问题标题】:R - dplyr mutate with function only checks first rowR - dplyr mutate with function 只检查第一行
【发布时间】:2018-05-06 21:39:36
【问题描述】:

我有一个时间列表,我想将它们放入存储桶中。 即“9:00 PM”进入“7:00 PM - 12:00 AM”存储桶

函数如下:

bucket.start.time <- function(x) {
  if (strptime(x, format = "%I:%M %p") >= strptime("7:00", format = "%R") && 
      strptime(x, format = "%I:%M %p") < strptime("12:00", format = "%R")) {
    timebucket <- "7:00 AM - 11:59 AM"
  }
  if (strptime(x, format = "%I:%M %p") >= strptime("12:00", format = "%R") && 
      strptime(x, format = "%I:%M %p") <= strptime("16:30", format = "%R")) {
    timebucket <- "12:00 PM - 4:30 PM"
  }
  if (strptime(x, format = "%I:%M %p") > strptime("16:30", format = "%R") && 
      strptime(x, format = "%I:%M %p") < strptime("19:00", format = "%R")) {
    timebucket <- "4:31 PM - 6:59 PM"
  }
  if (strptime(x, format = "%I:%M %p") >= strptime("19:00", format = "%R") && 
      strptime(x, format = "%I:%M %p") < strptime("24:00", format = "%R")) {
    timebucket <- "7:00 PM - 12:00 AM"
  }
  return(timebucket)
} 

然后我使用 mutated 创建第二列:

mutate(Appointments, Time.Bucket = bucket.start.time(Start.Time))

我发现,由于第一行的 Start.Time 为“12:30 PM”,因此该函数专门用“12:00 PM - 4:30 PM”填充了 Time.Bucket 列。我怎样才能 mutate 将我的函数单独应用于每一行,而不是将其应用于第一行并将结果复制到其余行?

【问题讨论】:

  • 我认为你需要&amp; 而不是&amp;&amp;
  • 谢谢@MauritsEvers,我会试试的。我通过创建一个循环并让我的函数输出一个桶值向量来修复它。如果你是对的,那你的方法比我的好很多!
  • 这里绝对不需要使用for 循环。看看?base::logic&amp;vectorised 逻辑 OR 运算符,您在这里需要它。
  • 你的函数没有向量化:
  • @MauritsEvers 我有点明白发生了什么。我可以使用向量化 & 将这些 if 语句应用于我的整个开始时间向量。但是我有四个不同的条件语句,所以我有点困惑如何将四个逻辑向量组合成一列。我可以使用逻辑开关吗?我还需要输出一个向量吗?

标签: r function dplyr


【解决方案1】:

试试:

bucket.start.time =function(m){
  x=c("7:00 AM","12:00 PM","4:31 PM","7:00 PM","11:59 PM")
  x=strptime(x,format = "%I:%M %p")
  y=c("7:00 AM - 11:59 AM","12:00 PM - 4:30 PM",
      "4:31 PM - 6:59 PM","7:00 PM - 12:00 AM")

  cut(strptime(m,format = "%I:%M %p"),x,y)
}

mutate(Appointments, Time.Bucket = bucket.start.time(Start.Time))

【讨论】:

  • 这个很好用,非常简洁,谢谢!出于好奇,您是否看到一种方法可以使用 & 创建的逻辑向量来完成,类似于上面其他人的评论?
  • 为了避免 forloop,你可以使用 findInterval 函数.. 或者嵌套的 ifelse 语句... ifelse 是向量化的,而 if ..else。不是矢量化的。如果 ..else 必须采用长度为 1 的逻辑参数
【解决方案2】:

我不认为这是最好的答案,但我认为对我来说最重要的是输出一个向量。我使用了一个 for 循环来修改我的函数:

bucket.start.time2 <- function(x) {
  totalbuckets <- vector(mode="character", length=length(x))
  for (i in 1:length(x)) {  
    if (strptime(x[i], format = "%I:%M %p") >= strptime("7:00", format = "%R") && 
        strptime(x[i], format = "%I:%M %p") < strptime("12:00", format = "%R")) {
      timebucket <- "7:00 AM - 11:59 AM"
    }
    if (strptime(x[i], format = "%I:%M %p") >= strptime("12:00", format = "%R") && 
        strptime(x[i], format = "%I:%M %p") <= strptime("16:30", format = "%R")) {
      timebucket <- "12:00 PM - 4:30 PM"
    }
    if (strptime(x[i], format = "%I:%M %p") > strptime("16:30", format = "%R") && 
        strptime(x[i], format = "%I:%M %p") < strptime("19:00", format = "%R")) {
      timebucket <- "4:31 PM - 6:59 PM"
    }
    if (strptime(x[i], format = "%I:%M %p") >= strptime("19:00", format = "%R") && 
        strptime(x[i], format = "%I:%M %p") < strptime("24:00", format = "%R")) {
      timebucket <- "7:00 PM - 12:00 AM"
    }
    totalbuckets[i] <- timebucket
  }
  return(totalbuckets)
}

它现在在以下语句中起作用:

mutate(Appointments, Time.Bucket = bucket.start.time(Start.Time))

【讨论】:

    猜你喜欢
    • 2022-12-02
    • 2018-03-18
    • 2018-02-03
    • 1970-01-01
    • 2015-06-17
    • 1970-01-01
    • 2015-03-20
    • 1970-01-01
    • 2016-09-17
    相关资源
    最近更新 更多