微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

用户定义的data.table函数中的“回收”错误

如何解决用户定义的data.table函数中的“回收”错误

我已经连接了两个数据表,并且正在根据该数据的子集进行计算。当下面的代码不在我编写的函数中时,以下代码可以正常运行,但是当我尝试使用该函数时出现此错误

Error in `[.data.table`(poll.name,AQ.Date >= Cdate & AQ.Date < Cdate +  : 
  i evaluates to a logical vector length 159 but there are 2797432 rows. Recycling of logical i is no longer allowed as it hides more bugs than is worth the rare convenience. Explicitly use rep(...,length=.N) if you really need to recycle.

我的功能

 myfunc <- function(linked.dat,poll.name) {

  linked.dat[,`:=` (t1.avg = mean(poll.name[AQ.Date >= Cdate & AQ.Date < Cdate + 1],na.rm = TRUE),t2.avg = mean(poll.name[AQ.Date >= Cdate + 1 & AQ.Date < Cdate + 2],t3.avg = mean(poll.name[AQ.Date >= Cdate + 2 & AQ.Date <= Bdate],total.avg = mean(poll.name)),by = ID]

  linked.pollname <- linked.dat

  return(linked.pollname)

}

因此,在示例df中使用此功能将类似于:

myfunc(df,O3) 

一些数据:

df <- structure(list(O3 = c(21.1,27.3,23.8,29.5,27.1,31.6,25.8,31.2,14,19.1,15.5,15.6,28.6,16.9,27.4,30.1,24.4,21.2,22.1,26.1,19.9),AQ.Date = structure(c(3679,3681,3682,3683,3680,3685,3686,3687,3684,3689,3673,3675,3677,3678,3688,3692,3693,3695,3696),class = "Date"),ID = c("a","a","b","b"
    ),Cdate = structure(c(3673,3677),Bdate = structure(c(3690,3690,3696,Total_weeks = c(2.428571,2.428571,2.714286,2.714286)),row.names = c(NA,-22L),class = "data.frame")

setDT(df) 

我不明白此错误的含义。回收指的是什么?为什么只在函数内发生?如何调整功能解决错误

解决方法

一般回收

回收与如何将不同长度的向量组合到data.frame(以及其他一些地方)有关。 data.frame的每一列(以及data.tabletbl_df)的长度必须相同,并且当长度不同时,将对其进行回收

在大多数(全部?)基本R函数中,只要最长向量是较短向量的偶数倍,回收就会默默地进行。例如,

data.frame(x = 1,y = 1:3)
#   x y
# 1 1 1
# 2 1 2
# 3 1 3
data.frame(x = 1:2,y = 1:4)
#   x y
# 1 1 1
# 2 2 2
# 3 1 3
# 4 2 4

但是当提供不均匀的组合时,R会出错(通常,但并非在所有情况下):

data.frame(x = 1:3,y = 1:4)
# Error in data.frame(x = 1:3,y = 1:4) : 
#   arguments imply differing number of rows: 3,4

我个人认为回收是便利与安全之间的平衡,其中“便利”是我要向具有多行的框架中添加具有单个不变值的列,如上面的第一个示例所示; “安全”是指您可以确定每个函数返回的内容(例如长度)和令人惊讶的内容都不会被隐藏。

对于后者,考虑一个自定义函数(模仿which.min),该函数可以找到最小值的位置:

myfunc <- function(x) which(x == min(x)) # this is naive,do not use it

对于“正常”数据,它将返回单个值,如

set.seed(42)
myfunc(runif(10))
# [1] 8

但是,也许在处理整数或其他可能发生相等性的事物时(在某些罕见的numeric实例中),一个可能得到多个:

myfunc(sample(10,size = 11,replace = TRUE))
# [1]  2 10

因此,如果您依赖返回单个值,但返回两个或多个,则...您所依赖的内容可能会进行静默回收,而您却不明智。例如,

set.seed(3)
mydat <- data.frame(x = sample(10,size = 12,replace = TRUE))
mydat$y <- myfunc(mydat$x)
mydat
#     x y
# 1   5 4
# 2  10 8
# 3   7 4
# 4   4 8
# 5  10 4
# 6   8 8
# 7   8 4
# 8   4 8
# 9  10 4
# 10  7 8
# 11  8 4
# 12  8 8

从我的角度来看,只有当回收全为1时,回收才是“可接受的”……其他任何东西都可以在许多地方正确使用,但我认为应该明确。

tibble允许全或1,否则会出错:

library(tibble)
tibble(x = 1,y = 1:3)
# # A tibble: 3 x 2
#       x     y
#   <dbl> <int>
# 1     1     1
# 2     1     2
# 3     1     3
tibble(x = 1:2,y = 1:3)
# Error: Tibble columns must have compatible sizes.
# * Size 2: Existing data.
# * Size 3: Column `y`.
# i Only values of size one are recycled.

特定于您的问题

您正在尝试在O3结构之外对符号data.table进行非标准评估。我相信您打算根据其他条件采用用户提供的框架栏中的平均值。

这是解决问题的一种方法:传递一个字符串,并在get(poll.name)中使用data.table(在需要数据的任何地方)获取数据:

myfunc <- function(linked.dat,poll.name) {
  linked.dat[,`:=` (t1.avg = mean(get(poll.name)[AQ.Date >= Cdate & AQ.Date < Cdate + 1],na.rm = TRUE),t2.avg = mean(get(poll.name)[AQ.Date >= Cdate + 1 & AQ.Date < Cdate + 2],t3.avg = mean(get(poll.name)[AQ.Date >= Cdate + 2 & AQ.Date <= Bdate],total.avg = mean(get(poll.name))),by = ID]

  linked.pollname <- linked.dat

  return(linked.pollname)
}

myfunc(df,"O3") 
#       O3    AQ.Date ID      Cdate      Bdate Total_weeks t1.avg t2.avg   t3.avg total.avg
#  1: 21.1 1980-01-28  a 1980-01-22 1980-02-08    2.428571   19.1    NaN 24.60909     24.15
#  2: 27.3 1980-01-30  a 1980-01-22 1980-02-08    2.428571   19.1    NaN 24.60909     24.15
#  3: 23.8 1980-01-31  a 1980-01-22 1980-02-08    2.428571   19.1    NaN 24.60909     24.15
#  4: 29.5 1980-02-01  a 1980-01-22 1980-02-08    2.428571   19.1    NaN 24.60909     24.15
#  5: 23.8 1980-01-29  a 1980-01-22 1980-02-08    2.428571   19.1    NaN 24.60909     24.15
# ---                                                                                      
# 18: 24.4 1980-02-10  b 1980-01-26 1980-02-14    2.714286   15.6   28.6 23.51250     23.23
# 19: 21.2 1980-01-30  b 1980-01-26 1980-02-14    2.714286   15.6   28.6 23.51250     23.23
# 20: 22.1 1980-02-11  b 1980-01-26 1980-02-14    2.714286   15.6   28.6 23.51250     23.23
# 21: 26.1 1980-02-13  b 1980-01-26 1980-02-14    2.714286   15.6   28.6 23.51250     23.23
# 22: 19.9 1980-02-14  b 1980-01-26 1980-02-14    2.714286   15.6   28.6 23.51250     23.23

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。