使用 R 中的 for 和 if 语句在fluidRow() 中进行迭代
Posted
技术标签:
【中文标题】使用 R 中的 for 和 if 语句在fluidRow() 中进行迭代【英文标题】:Iteration inside fluidRow() with for and if statement in R 【发布时间】:2020-11-24 04:08:52 【问题描述】:我正在尝试在 bs4TabItem 中使用fluidRow,它最多有 3 个 bs4UserCard 项目。 FluidRows 应该在 for 循环中动态构建,并且最大。 3 bs4UserCard 也应该在 for 循环中动态构建。下面是代码的sn-p。我已经根据其他建议尝试了 UI 和服务器部分中的代码,但它仍然不起作用。
# Get number of rows from dataset
records = nrow(candidatesDF)
# Each row will have max. 3 items
numRows = ceiling(nrow(candidatesDF) / 3)
numRows = c(1:numRows)
count = 0
offset = 3
candidates = bs4TabItem(tabName = "candidates",
for (row in numRows)
fluidRow(
if (records < offset)
offset = records
for (column in 1:offset)
count = count + 1
# Convert the names to a more legible format
name = explode(candidatesDF[count, "Candidate"], sep = ", ")
name = paste0(name[2], ' ', name[1])
name = capitalizeStrings(name, all.words = TRUE, lower.back = TRUE)
# Convert the names to the img name format
imgName = explode(name, sep = " ")
imgName = tolower(implode(imgName, "_"))
imgUrl = paste0("img/", imgName, ".png")
# Create a user card on each iteration.
bs4UserCard(
title = name,
subtitle = candidatesDF[count, "Party"],
type = NULL,
width = 4,
src = imgUrl,
status = "danger",
closable = TRUE,
elevation = 4,
imageElevation = 4,
fluidRow(
column(
width = 4,
descriptionBlock(header = "District",
text = capitalizeStrings(candidatesDF[count, "District"],
all.words = TRUE, lower.back = TRUE ))
),
column(
width = 4,
descriptionBlock(header = "Votes",
text = candidatesDF[count, "Votes"])
),
column(
width = 4,
descriptionBlock(header = "Result",
text = candidatesDF[count, "Result"], right_border = FALSE)
)
)
)
records = records - 1
)
)
使用 if 语句我得到这个错误
Possible missing comma at:
87: for (row in fluidRows)
^
如果我仅出于测试目的删除 if 语句,我会收到此错误
Warning: Error in explode: Assertion on 'x' failed: May not be NA.
我不确定explode 中的x 如何是NA,因为我在数据集中没有任何NA 值。当我逐行运行代码测试explode函数时,返回了预期的结果,所以我不明白为什么NA。
尽管如此,我的目标是创建 x 数量的 fluidRows,每行最多包含 3 个项目,这些项目的信息是从数据集中动态生成的。 ################################################## ###################### 我已更新代码以反映使用 lapply() 的建议。
# Get number of rows from dataset
records = nrow(candidatesDF)
# Each row will have max. 3 items
numRows = ceiling(nrow(candidatesDF) / 3)
numRows = c(1:numRows)
count = 0
offset = 3
checkOffset = function(records, offset)
if (records < offset)
offset = records
return(offset)
candidates = bs4TabItem(tabName = "candidates",
lapply(numRows, function(r)
fluidRow(
lapply(1:checkOffset(records, offset), function(c)
count = count + 1
print(count)
# Convert the names to a more legible format
name = explode(candidatesDF[count, "Candidate"], sep = ", ")
name = paste0(name[2], ' ', name[1])
name = capitalizeStrings(name, all.words = TRUE, lower.back = TRUE)
# Convert the names to the img name format
imgName = explode(name, sep = " ")
imgName = tolower(implode(imgName, "_"))
imgUrl = paste0("img/", imgName, ".png")
records = records - 1
# Create a user card on each iteration.
bs4UserCard(
title = name,
subtitle = candidatesDF[count, "Party"],
type = NULL,
width = 4,
src = imgUrl,
status = "primary",
closable = TRUE,
elevation = 4,
imageElevation = 4,
fluidRow(
column(
width = 4,
descriptionBlock(header = "District",
text = capitalizeStrings(candidatesDF[count, "District"],
all.words = TRUE, lower.back = TRUE ))
),
column(
width = 4,
descriptionBlock(header = "Votes",
text = candidatesDF[count, "Votes"])
),
column(
width = 4,
descriptionBlock(header = "Result",
text = candidatesDF[count, "Result"], right_border = FALSE)
)
)
)
)
)
)
虽然这对接近预期结果有很大帮助,但每个网格中的每张卡片都是相同的。那是因为count变量不递增,record变量也不递增。
提前致谢。
【问题讨论】:
你想让这个响应吗?或者只是试图在服务器启动时硬编码元素的数量?for
R 中的循环不返回值。你应该做的是建立一个list()
的对象,你想插入到 UI 中,然后将该列表传递给fluidRow()
。如果您提供最小的reproducible example,则更容易提供帮助。删除任何对问题不重要的代码。
请尝试lapply
而不是for
循环。正如 MrFlick 指出的那样,MRE 将有助于识别任何其他问题。
@MrFlick 我希望循环使用代表数据集中每一行的索引生成所需的值。我认为我在问题中放置的代码足以重现,所以我不确定要添加什么,并且链接不太清楚,因为有很多可能性。
@YBS 我已经删除了 for 循环并用 lapply 替换它们。这达到了一定程度。它能够生成预期的行数和列数,但不会在每次迭代中增加计数变量。因此它将显示相同的用户卡。
@Ravi,如果没有完全可重现的代码,很难调试。我会考虑的两个项目是:(1)不需要定义numRows = c(1:numRows)
,而是你应该定义lapply(1:numRows, …
,(2)对于第二个lapply
,请尝试lapply(1:(checkOffset(records, offset)),...
【参考方案1】:
根据@YBS 的建议将 for 循环切换到 lapply 后,我的主要问题变成了弄清楚为什么 count 和 record 变量在第一次 lapply 迭代后不会保持它们的值。
答案是使用 can lapply not modify variables in a higher scope找到解释。
【讨论】:
以上是关于使用 R 中的 for 和 if 语句在fluidRow() 中进行迭代的主要内容,如果未能解决你的问题,请参考以下文章