【发布时间】:2021-07-28 16:19:30
【问题描述】:
首先,这是一个通用问题,我希望有知识的人能够指出我实现我想做的方法的正确方向。因此,我没有可重现的示例要分享,但我将提供一些示例代码,希望能理解我正在尝试做的事情。
我有一个 R Shiny 仪表板应用程序。此应用程序使用在全球环境中生成的许多不同数据集(即不在服务器内)。在服务器中,需要根据用户输入对每个数据集应用过滤器。因此,这些数据集是被动的。
我目前对每个数据集都有单独的代码块,如下面的示例代码所示。这行得通。但是,我希望对此进行动态编程,这样我就可以将相同的代码应用于数据集列表,而无需为每个数据集单独复制和编辑相同的代码块。
下面是当前代码块的示例。他们调用处理数据集的过滤器函数。例如,代码的后面部分可以调用“filtered_data_apple()”,并且可以按预期工作。
filtered_data_apple <- reactive({
data <- filter_data('apple',as.data.table(df_apple))
data
})
filtered_data_banana <- reactive({
data <- filter_data('banana',as.data.table(df_banana))
data
})
filtered_data_cherry <- reactive({
data <- filter_data('cherry',as.data.table(df_cherry))
data
})
我想要的是能够提供一个列表(在这个例子中是水果),并让服务器循环遍历它们并将相同的代码块应用到所有它们以及代码的其他部分能够调用他们生成的数据集而不会出现任何错误。
下面的代码不起作用,但希望能证明我正在尝试做的事情:
for (fruit in c('apple','banana','cherry')){
filtered_data_name <- paste('filtered_data_',fruit,sep="")
df_name <- paste('df_',fruit,sep="")
assign(filtered_data_name,
reactive({
data <- filter_data(fruit,as.data.table(get(df_name)))
data
})
)
}
我相信上述方法失败是因为在 Shiny 服务器中评估代码时。我认为“fruit”的值在每次迭代中最终都是相同的(列表中的最后一个值,“cherry”)。所以它适用于“樱桃”数据集,但仅此而已。我也尝试在本地语句中包含循环内的代码,但这不起作用,因为生成的数据集仍然包含在本地环境中,并且不能从外部调用。我也尝试过使用重复循环,但由于与 for 循环相同的原因,它也失败了。在所有迭代中,fruit 的值将是“cherry”。
希望我已经足够清楚地传达这个问题,我希望有人能够提供正确的方法来解决这个问题。肯定有什么吧?
谢谢!
编辑:为清楚起见,数据集可以包含彼此完全不同的列。因此,为什么它们是单独的数据集。它们也是非常大的数据集,所以我想限制正在进行的过滤量,以便它为该数据集过滤一次,而不是每次调用都过滤一个更大的数据集,这需要更长的运行时间。
【问题讨论】:
-
为什么需要单独的数据集? (
filtered_data_apple(),filtered_data_banana())等?你能把它们放在一个可以避免所有问题的列表中吗? -
我也建议和 Ronak 一样,要么列出,要么你可以,如果它们是小数据帧/具有相同的列,数据帧的格式类型更长
-
我同意其他评论员的观点 - 反应式或动态过滤列表似乎是更好的选择,但如果由于我们尚不知道的原因需要单独的反应式,那么 惰性评估 可能是一个因素。今天早些时候的This post 可能是相关的。如果做不到这一点,modularisation 将带来明显的好处并提供简单的解决方案。
-
@RonakShah 我确定你的意思。您的意思是您将创建单个数据集并将其添加到(数据表)列表中,该列表作为反应表达式的值传回,然后使用索引访问列表?我从来没有尝试过。免责声明,我的应用与水果无关。我只在示例代码中使用了它们。数据集包含不同的列。因此,为什么我需要单独的数据集。 ...继续下面
-
...在代码的其他部分,可以将值传递给函数(例如“apple”,但可以是任何水果)。这样就找到了苹果对应的数据集。如果它包含在列表的一个元素中,它肯定必须通过索引号来引用它,不是吗?那会假设它在整个程序中始终保持不变?