我已经在SO上进行了广泛的搜索,但找不到与我的问题完全相同的答案。
我正在尝试使用从inputs
数据帧读取多变量参数的函数来生成一些时间序列条目。 {x,y,z,...}
中的每组变量inputs
都会生成一个时间序列数据帧;的收藏需要不公开。
inputs
数据帧本身是混合类型(字符和双精度),因此我遇到了apply
函数的问题,据我了解,该函数在内部会转换为矩阵对象,因此会失败。
mapply
似乎是理想的候选对象(并且过程运行,但是结果无效,因为时间序列生成函数本身在生成正态分布时被矢量化了
下面的代码可以运行,但是给出错误的结果
library(dplyr)
library(truncnorm)
forecast_curve <- function(case_id,
wal,
wal_sd,
amt,
n_qrtr) {
result <-
tibble(case_id = case_id,
quarter = seq(1, n_qrtr, 1)
) %>%
mutate(
amt_qrtr = amt *
dtruncnorm(seq(1, n_qrtr, 1),a = 1,b = n_qrtr,mean = wal, sd = wal_sd)
)
return(result)
}
#Generate inputs
inputs <-
tibble(
case_id = letters[1:10],
wal = seq(5,14,1),
wal_sd = rep(4,10),
total_amt_FC = c(10,9,8,7,6,5,4,3,2,1),
n_qrtr = rep(12,10)
)
#outputs function
outputs <- function(){
tmp <-
mapply(
forecast_curve,
inputs$case_id,
inputs$wal,
inputs$wal_sd,
inputs$total_amt_FC,
inputs$n_qrtr
)
tmp <-
as.data.frame(apply(tmp, 1, unlist)) %>%
tibble() %>%
mutate(
quarter = as.numeric(quarter),
amt_qrtr = as.numeric(amt_qrtr)
) %>%
arrange(case_id,quarter)
return(tmp)
}
如果仔细查看case_id == a
的结果,则结果看起来像这样
print(outputs() %>% filter (case_id == 'a'), n= 30)
case_id quarter amt_qrtr
<fct> <dbl> <dbl>
1 a 1 80
2 a 2 65
3 a 3 52
4 a 4 39
5 a 5 89
6 a 6 94
7 a 7 95
8 a 8 96
9 a 9 95
10 a 10 94
11 a 11 89
12 a 12 80
但是,相同参数(与inputs
的第一行匹配)的正确结果是
#Correct example output
forecast_curve('a',5,4,10,12)
case_id quarter amt_qrtr
<chr> <dbl> <dbl>
1 a 1 0.755
2 a 2 0.940
3 a 3 1.10
4 a 4 1.21
5 a 5 1.24
6 a 6 1.21
7 a 7 1.10
8 a 8 0.940
9 a 9 0.755
10 a 10 0.570
11 a 11 0.404
12 a 12 0.269
从类似的问题上看来,do.call
是解决方案,但是我无法在下面的案例中使用它。
在此先感谢您的指导
答案 0 :(得分:1)
您使问题变得更加棘手。假设您有一个类似forecast_curve
的函数,则可以直接使用mapply
调用该函数。不需要outputs
函数。
在控制台窗口中,输入?mapply
以查看mapply
的帮助,以便您可以看到所需的参数。 mapply
将调用为FUN
指定的函数,并将FUN
参数中每个向量的第一个值传递给...
。然后它将使用...
参数中每个向量的第二个值再次调用该函数。等等。如果设置SIMPLIFY = F
,则结果将始终以列表形式返回。
由于forecast_curve
返回了一个小标题,因此当您将mapply
与FUN = forecast_curve
一起使用时,您将返回一个小标题列表。因此,以下代码将返回一个包含10个小节的列表,inputs
小节的每一行一个。
listOfTibbles =
mapply(
forecast_curve,
inputs$case_id,
inputs$wal,
inputs$wal_sd,
inputs$total_amt_FC,
inputs$n_qrtr,
SIMPLIFY = F
)
如果要将所有这些小节合并为一个小节,则需要使用rbind
,而不是unlist
。您可以这样做:
singleTibble = rbind(listOfTibbles[[1]], listOfTibbles[[2]], listOfTibbles[[3]], listOfTibbles[[4]], listOfTibbles[[5]], listOfTibbles[[6]], listOfTibbles[[7]], listOfTibbles[[8]], listOfTibbles[[9]], listOfTibbles[[10]])
但是do.call
提供了一种更简单的方法。 do.call
使用列表中的值作为该函数的参数来调用一个函数(在本例中为rbind
)。因此,您可以使用以下方法获得相同的结果:
singleTibble = do.call(rbind, listOfTibbles)