【问题标题】:Writing R functions to support vectors编写 R 函数来支持向量
【发布时间】:2015-09-29 20:34:39
【问题描述】:

我有这个功能:

pcal.getPeriodForDate <- function(date_) {
    dateObject <- as.POSIXlt(date_)
    calendarStart <- pcal.getCalendarStart(dateObject$year + 1900)

    difference <- dateObject - calendarStart

    if(difference < 0) {
        calendarStart <- pcal.getCalendarStart(dateObject$year + 1899)
        difference <- dateObject - calendarStart
    }

    period <- difference / 28

    week <- ifelse(period < 1, ceiling(period * 4), ceiling((period - floor(period)) * 4))

    return(list(Period = as.numeric(ceiling(period)), Week = week))
}

我还有一个结构如下的数据框

> str(sells)
'data.frame':   73738 obs. of  4 variables:
 $ LOC_NBR: chr  "2" "2" "2" "2" ...
 $ SLS_DT : Date, format: "2015-02-01" "2015-02-02" "2015-02-03" "2015-02-04" ...
 $ SALES  : num  1 2 3 4 5 ...

我希望能够做到这一点:

sells$pd <- pcal.getPeriodForDate(sells$SLS_DT)$Period

但是,我收到大量警告:

Warning messages:
1: In if (year < 2000) { :
  the condition has length > 1 and only the first element will be used
2: In seedYear:year :
  numerical expression has 73738 elements: only the first used
3: In if (difference < 0) { :
  the condition has length > 1 and only the first element will be used
4: In if (year < 2000) { :
  the condition has length > 1 and only the first element will be used
5: In seedYear:year :
  numerical expression has 73738 elements: only the first used

该函数在传递一个值时工作正常:

> pcal.getPeriodForDate('2015-09-29')
$Period
[1] 9

$Week
[1] 3

我怎样才能做到这一点?

【问题讨论】:

  • could not find function "pcal.getCalendarStart"
  • 最简单/最快的方法是矢量化函数v &lt;- Vectorize(pcal.getPeriodForDate)v(sells$SLS_DT)

标签: r function vector


【解决方案1】:

if 函数在 R 中没有向量化,这意味着您只能将它与长度为 1 的向量一起使用。将if 与更大的向量一起使用会导致您收到警告,这是一个非常严重的警告,不应该是忽略 if 仅使用向量的第一个元素,这很可能会给您带来麻烦。看这个简单的案例:

> if(c(1,-5,3) > 0) print('hello')
[1] "hello"
Warning message:
In if (c(1, -5, 3) > 0) print("hello") :
  the condition has length > 1 and only the first element will be used

在这种情况下,尽管上面的向量中有一个-5,但返回hello 只是因为if 检查了向量的第一个元素。

要将if 与向量一起使用,您有三个选项:

全部

当您希望向量的每个元素都确认条件时,将其与函数 all 一起使用:

if( all(c(1,-5,3) > 0) ) print('hello')
#this does not return anything

任何

当您希望至少一个元素来确认条件时,将其与函数any 一起使用:

> if( any(c(1,-5,3) > 0) ) print('hello')
[1] "hello"

申请家庭

当您需要一个与所检查的向量(此处为c(1,-5,3))相同大小的向量时,将它与 *apply 系列一起使用,其中每个元素都将根据条件进行检查:

> vapply(c(1,-5,3), function(x) {
   if (x > 0) 'Hello' else NA_character_
 }, 
 character(1))
[1] "Hello" NA      "Hello"

我无法运行您的函数来告诉您您需要上述哪个版本,因为我不知道difference 的使用方式或pcal.getCalendarStart 的作用,但这应该足以帮助您解决收到的警告。根据您想要的行为方式使用上述其中一种,您应该不会收到任何警告。

【讨论】:

  • 很抱歉。其他函数以相同的方式编写,即未矢量化。我对函数进行了 Vectorize,这给了我需要的结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-22
  • 2016-09-25
  • 1970-01-01
  • 1970-01-01
  • 2016-06-21
  • 1970-01-01
  • 2017-02-24
相关资源
最近更新 更多