R data.table 根据 j 中的列动态过滤行
R data.table dynamically filter rows based on columns in j
我正在处理一个需要为少数预测变量生成 MAPE 的需求。为此,我使用 MAP 函数在 data.table 中生成带有 MAPE 值的摘要 table。因此结果输出应该有 4 行 x 6 列,每个城市 1 行和 1 个城市列后跟 a1、a2、a3、a4、a5,每个单元格中都有 MAPE 值。
下面是我使用的示例数据和代码(注意 - 被认为是 a1、a2、a3....实际和 p1、p2、p3...如预测)-
library(data.table)
set.seed(123)
id <- seq(1001,1100,1)
city <- sample(1:4,100,replace = T)
a1 <- sample(1:100,100,replace = T)
a2 <- sample(1:100,100,replace = T)
a3 <- sample(1:100,100,replace = T)
a4 <- sample(1:100,100,replace = T)
a5 <- sample(1:100,100,replace = T)
p1 <- sample(1:100,100,replace = T)
p2 <- sample(1:100,100,replace = T)
p3 <- sample(1:100,100,replace = T)
p4 <- sample(1:100,100,replace = T)
p5 <- sample(1:100,100,replace = T)
df1 <- as.data.table(data.frame(id,city,a1,a2,a3,a4,a5,p1,p2,p3,p4,p5))
sum1 <- df1[, Map(function(x,y) mean(as.numeric(abs(get(x)-get(y))/get(x))*100),
paste("a",1:5, sep = ""),
paste("p",1:5, sep = "")),by=city]
现在我想为 x==y
然后 x > y
和 x < y
的行生成相同的摘要......我认为最简单的方法是在 i 中传递它,但是如何做到这一点我没有得到.....当我尝试将它作为 function(x,y) get(x)==get(y)
传递时它给出错误
i has not evaluated to logical, integer or double
请推荐
更新后的答案: 由于您希望每个 ==
、>
和 <
有 3 个单独的数据表,我使用了lapply
使用您在 post 中 post 编写的相同代码逐一处理这些操作。
运算符(例如 ==
)作为 z
传递给 Map
。因为这是一个 'operator' 你不能使用 get(z)
所以为了解决这个问题我使用 do.call
应用 fn
函数(即 ==
运算符)变量列表。
在 Map
函数中,我首先根据 fn
值(即 z
)过滤数据,如 x1
和 y1
。然后对这些子集应用MAPE公式得到最终结果。
lapply(c("==", ">", "<"),
function(z) df1[,
Map(function(x, y, fn = z){
x1 <- get(x)[do.call(fn, list(get(x), get(y)))]
y1 <- get(y)[do.call(fn, list(get(x), get(y)))]
mean(as.numeric(abs(x1 - y1) / x1) * 100)
},
paste0("a", 1:5),
paste0("p", 1:5),
z),
by = city])
我正在处理一个需要为少数预测变量生成 MAPE 的需求。为此,我使用 MAP 函数在 data.table 中生成带有 MAPE 值的摘要 table。因此结果输出应该有 4 行 x 6 列,每个城市 1 行和 1 个城市列后跟 a1、a2、a3、a4、a5,每个单元格中都有 MAPE 值。
下面是我使用的示例数据和代码(注意 - 被认为是 a1、a2、a3....实际和 p1、p2、p3...如预测)-
library(data.table)
set.seed(123)
id <- seq(1001,1100,1)
city <- sample(1:4,100,replace = T)
a1 <- sample(1:100,100,replace = T)
a2 <- sample(1:100,100,replace = T)
a3 <- sample(1:100,100,replace = T)
a4 <- sample(1:100,100,replace = T)
a5 <- sample(1:100,100,replace = T)
p1 <- sample(1:100,100,replace = T)
p2 <- sample(1:100,100,replace = T)
p3 <- sample(1:100,100,replace = T)
p4 <- sample(1:100,100,replace = T)
p5 <- sample(1:100,100,replace = T)
df1 <- as.data.table(data.frame(id,city,a1,a2,a3,a4,a5,p1,p2,p3,p4,p5))
sum1 <- df1[, Map(function(x,y) mean(as.numeric(abs(get(x)-get(y))/get(x))*100),
paste("a",1:5, sep = ""),
paste("p",1:5, sep = "")),by=city]
现在我想为 x==y
然后 x > y
和 x < y
的行生成相同的摘要......我认为最简单的方法是在 i 中传递它,但是如何做到这一点我没有得到.....当我尝试将它作为 function(x,y) get(x)==get(y)
传递时它给出错误
i has not evaluated to logical, integer or double
请推荐
更新后的答案: 由于您希望每个 ==
、>
和 <
有 3 个单独的数据表,我使用了lapply
使用您在 post 中 post 编写的相同代码逐一处理这些操作。
运算符(例如 ==
)作为 z
传递给 Map
。因为这是一个 'operator' 你不能使用 get(z)
所以为了解决这个问题我使用 do.call
应用 fn
函数(即 ==
运算符)变量列表。
在 Map
函数中,我首先根据 fn
值(即 z
)过滤数据,如 x1
和 y1
。然后对这些子集应用MAPE公式得到最终结果。
lapply(c("==", ">", "<"),
function(z) df1[,
Map(function(x, y, fn = z){
x1 <- get(x)[do.call(fn, list(get(x), get(y)))]
y1 <- get(y)[do.call(fn, list(get(x), get(y)))]
mean(as.numeric(abs(x1 - y1) / x1) * 100)
},
paste0("a", 1:5),
paste0("p", 1:5),
z),
by = city])