如何将自定义函数应用于嵌套数据框?
How to apply a custom function to nested dataframes?
我正在尝试将自定义函数应用于嵌套数据框
我想应用机器学习算法来预测 NA 值
网上看了一会,觉得这里用map函数最合适
我有一段代码嵌套数据框,然后将数据拆分为测试 (data3) 和训练 (data2) 集 - 测试数据集包含要预测的列的所有空值,并且包含用于训练 ML 模型的所有非空值的训练
dmaExtendedDataNA2 <- dmaExtendedDataNA %>%
group_by(dma) %>%
nest() %>%
mutate(data2 = map(data, ~filter(., !(is.na(mean_night_flow)))),
data3 = map(data, ~filter(., is.na(mean_night_flow))))
这是我打算使用的功能:
my_function (test,train) {
et <- extraTrees(x = train, y = train[, "mean_night_flow"], na.action = "fuse", ntree = 1000, nodesize = 2, mtry = ncol(train) * 0.9 )
test1 <- test
test1[ , "mean_night_flow"] <- 0
pred <- predict(et, newdata = test1[, "mean_night_flow"])
test1[ , "mean_night_flow"] <- pred
return(test1)
我已经尝试了以下代码,但是它不起作用:
dmaExtendedDataNA2 <- dmaExtendedDataNA %>%
group_by(dma) %>%
nest() %>%
mutate(data2 = map(data, ~filter(., !(is.na(mean_night_flow)))),
data3 = map(data, ~filter(., is.na(mean_night_flow))),
data4 = map(data3, data2, ~my_function(.x,.y)))
它给出了以下错误:
Error: Index 1 must have length 1, not 33
这表明它需要一列而不是整个数据框。我怎样才能让它工作?
非常感谢
如果不对您的数据进行测试,我认为您使用了错误的 map
函数。 purrr::map
适用于 一个 参数(一个列表,一个向量,等等)和 returns 一个列表。您向它传递了两个值(data3
和 data2
),因此我们需要使用:
dmaExtendedDataNA2 <- dmaExtendedDataNA %>%
group_by(dma) %>%
nest() %>%
mutate(data2 = map(data, ~filter(., !(is.na(mean_night_flow)))),
data3 = map(data, ~filter(., is.na(mean_night_flow))),
data4 = map2(data3, data2, ~my_function(.x,.y)))
如果您发现自己需要两个以上,则需要 pmap
。您可以对 1 个或 2 个参数使用 pmap
,实际上是一样的。从 map
迁移到 pmap
的两个最大差异是:
您的参数需要包含在一个列表中,所以
map2(data3, data12, ...)
变成
pmap(list(data3, data12), ...)
你指的是双点号位置,..1
、..2
、..3
等,所以
~ my_function(.x, .y)
变成
~ my_function(..1, ..2)
一种可以稍微简化您的整体流程的替代方法。
my_function (test, train = NULL, fld = "mean_night_flow") {
if (is.null(train)) {
train <- test[ !is.na(test[[fld]]),, drop = FALSE ]
test <- test[ is.na(test[[fld]]),, drop = FALSE ]
}
et <- extraTrees(x = train, y = train[, fld], na.action = "fuse", ntree = 1000, nodesize = 2, mtry = ncol(train) * 0.9 )
test1 <- test
test1[ , fld] <- 0
pred <- predict(et, newdata = test1[, fld])
test1[ , fld] <- pred
return(test1)
}
根据您的字段缺失自动填充 train
。 (我还对其进行了参数化,以防您需要在不同的字段上 train/test。)这会将您的使用更改为
dmaExtendedDataNA2 <- dmaExtendedDataNA %>%
group_by(dma) %>%
nest() %>%
mutate(data4 = map(data, ~ my_function(.x, fld = "mean_night_flow")))
(命名 fld=
很重要,否则会与 train
混淆。)
如果您计划稍后在管道或分析中重复使用 data2
and/or data3
,那么这一步不一定是您需要的。
注意:我怀疑你的功能测试不足或不完整。您将所有 0
分配给 test1[,"mean_night_flow"]
然后在对 predict
的调用中使用这些零这一事实似乎令人怀疑。我可能会遗漏一些东西,但我希望也许
test1 <- test
pred <- predict(et, newdata = test1)
test1[ , fld] <- pred
return(test1)
(尽管使用 tibble
或 data.frame
复制到 test1
基本上是不必要的,因为它是就地复制的并且原始框架未被触动;如果你使用的是 class data.table
).
我正在尝试将自定义函数应用于嵌套数据框
我想应用机器学习算法来预测 NA 值
网上看了一会,觉得这里用map函数最合适
我有一段代码嵌套数据框,然后将数据拆分为测试 (data3) 和训练 (data2) 集 - 测试数据集包含要预测的列的所有空值,并且包含用于训练 ML 模型的所有非空值的训练
dmaExtendedDataNA2 <- dmaExtendedDataNA %>%
group_by(dma) %>%
nest() %>%
mutate(data2 = map(data, ~filter(., !(is.na(mean_night_flow)))),
data3 = map(data, ~filter(., is.na(mean_night_flow))))
这是我打算使用的功能:
my_function (test,train) {
et <- extraTrees(x = train, y = train[, "mean_night_flow"], na.action = "fuse", ntree = 1000, nodesize = 2, mtry = ncol(train) * 0.9 )
test1 <- test
test1[ , "mean_night_flow"] <- 0
pred <- predict(et, newdata = test1[, "mean_night_flow"])
test1[ , "mean_night_flow"] <- pred
return(test1)
我已经尝试了以下代码,但是它不起作用:
dmaExtendedDataNA2 <- dmaExtendedDataNA %>%
group_by(dma) %>%
nest() %>%
mutate(data2 = map(data, ~filter(., !(is.na(mean_night_flow)))),
data3 = map(data, ~filter(., is.na(mean_night_flow))),
data4 = map(data3, data2, ~my_function(.x,.y)))
它给出了以下错误:
Error: Index 1 must have length 1, not 33
这表明它需要一列而不是整个数据框。我怎样才能让它工作?
非常感谢
如果不对您的数据进行测试,我认为您使用了错误的 map
函数。 purrr::map
适用于 一个 参数(一个列表,一个向量,等等)和 returns 一个列表。您向它传递了两个值(data3
和 data2
),因此我们需要使用:
dmaExtendedDataNA2 <- dmaExtendedDataNA %>%
group_by(dma) %>%
nest() %>%
mutate(data2 = map(data, ~filter(., !(is.na(mean_night_flow)))),
data3 = map(data, ~filter(., is.na(mean_night_flow))),
data4 = map2(data3, data2, ~my_function(.x,.y)))
如果您发现自己需要两个以上,则需要 pmap
。您可以对 1 个或 2 个参数使用 pmap
,实际上是一样的。从 map
迁移到 pmap
的两个最大差异是:
您的参数需要包含在一个列表中,所以
map2(data3, data12, ...)
变成
pmap(list(data3, data12), ...)
你指的是双点号位置,
..1
、..2
、..3
等,所以~ my_function(.x, .y)
变成
~ my_function(..1, ..2)
一种可以稍微简化您的整体流程的替代方法。
my_function (test, train = NULL, fld = "mean_night_flow") {
if (is.null(train)) {
train <- test[ !is.na(test[[fld]]),, drop = FALSE ]
test <- test[ is.na(test[[fld]]),, drop = FALSE ]
}
et <- extraTrees(x = train, y = train[, fld], na.action = "fuse", ntree = 1000, nodesize = 2, mtry = ncol(train) * 0.9 )
test1 <- test
test1[ , fld] <- 0
pred <- predict(et, newdata = test1[, fld])
test1[ , fld] <- pred
return(test1)
}
根据您的字段缺失自动填充 train
。 (我还对其进行了参数化,以防您需要在不同的字段上 train/test。)这会将您的使用更改为
dmaExtendedDataNA2 <- dmaExtendedDataNA %>%
group_by(dma) %>%
nest() %>%
mutate(data4 = map(data, ~ my_function(.x, fld = "mean_night_flow")))
(命名 fld=
很重要,否则会与 train
混淆。)
如果您计划稍后在管道或分析中重复使用 data2
and/or data3
,那么这一步不一定是您需要的。
注意:我怀疑你的功能测试不足或不完整。您将所有 0
分配给 test1[,"mean_night_flow"]
然后在对 predict
的调用中使用这些零这一事实似乎令人怀疑。我可能会遗漏一些东西,但我希望也许
test1 <- test
pred <- predict(et, newdata = test1)
test1[ , fld] <- pred
return(test1)
(尽管使用 tibble
或 data.frame
复制到 test1
基本上是不必要的,因为它是就地复制的并且原始框架未被触动;如果你使用的是 class data.table
).