在空的 tibble 中,列类型会根据添加第一行的方式而改变
Posted
技术标签:
【中文标题】在空的 tibble 中,列类型会根据添加第一行的方式而改变【英文标题】:In an empty tibble, column types change depending on how the first row is added 【发布时间】:2020-08-13 21:12:48 【问题描述】:我正在开发一个闪亮的应用程序,其中一部分需要编辑(更改现有值,添加新行)到各种小标题。需要编辑许多小标题,每个小标题都有不同的列名和数据类型。我想使用通用编辑器。每个小标题都是空的。
我用零行和键入的列创建小标题。这行得通。
makeTibble <- function()
tibble(W=character(), X=numeric(), Y=logical(), Z=structure(NA_real_, class = "Date"))
v <- reactiveValues(data=makeTibble())
当我添加一行并直接按名称操作每一列时,列类型被保留:
observeEvent(input$addDirect,
v$data <- v$data %>% add_row(W="Testing...", X=pi, Y=TRUE, Z=as.Date("2020-04-29", origin="1970-01-01"))
)
但这意味着每个 tibble 都有一个不同的编辑器,并且每次相应 tibble 的结构发生变化时都必须编辑每个编辑器(它会)。所以我尝试自动添加新行:
newValues <- c("W"="Testing...", "X"=pi, "Y"=TRUE, "Z"=as.Date("2020-04-29"))
observeEvent(input$addLoop,
columns <- v$data %>% dplyr::summarise_all(class) %>% tidyr::gather(variable, class)
v$data <- v$data %>% add_row()
for (f in columns$variable)
v$data <- v$data %>% mutate(!!f := newValues[f])
)
但这会将 tibble 中每一列的类型转换为字符。不是我想要的。所以我尽量保留每一列的类型:
asTypedValue <- function(value, type)
print(paste0("type: ", type, "; value: ", value))
switch(type,
"character"="Testing...",
"logical"=TRUE,
"numeric"=pi,
"Date"=as.Date("2020-04-29", origin="1970-01-01")
)
observeEvent(input$addTypedLoop,
columns <- v$data %>% summarise_all(class) %>% gather(variable, class)
v$data <- v$data %>% add_row()
targetRow <- nrow(v$data)
for (col in columns$variable)
colClass <- (columns %>% filter(variable == col))$class
v$data <- v$data %>% mutate(!! col := ifelse(row_number() == targetRow, asTypedValue(newValues[col], colClass), !! col))
)
这适用于character
、logical
和numeric
列,但Date
列将转换为dbl
。我做错了什么?
这是一个 foo
Shiny 应用程序来演示发生了什么。
library(shiny)
library(tidyverse)
ui <- fluidPage(
wellPanel(
actionButton("reset", "Reset"),
actionButton("addDirect", "Add row (direct manipulation)"),
actionButton("addLoop", "Add row (apply loop)"),
actionButton("addTypedLoop", "Add row (apply loop with typing)")
),
wellPanel(
verbatimTextOutput("tibble")
)
)
server <- function(input, output)
newValues <- c("W"="Testing...", "X"=pi, "Y"=TRUE, "Z"=as.Date("2020-04-29"))
makeTibble <- function()
tibble(W=character(), X=numeric(), Y=logical(), Z=structure(NA_real_, class = "Date"))
v <- reactiveValues(
data=makeTibble()
)
output$tibble <- renderPrint(
v$data
)
observeEvent(input$reset,
v$data <- makeTibble()
)
observeEvent(input$addDirect,
v$data <- v$data %>% add_row(W="Testing...", X=pi, Y=TRUE, Z=as.Date("2020-04-29", origin="1970-01-01"))
)
observeEvent(input$addLoop,
columns <- v$data %>% dplyr::summarise_all(class) %>% tidyr::gather(variable, class)
v$data <- v$data %>% add_row()
for (f in columns$variable)
v$data <- v$data %>% mutate(!!f := newValues[f])
)
asTypedValue <- function(value, type)
print(paste0("type: ", type, "; value: ", value))
switch(type,
"character"="Testing...",
"logical"=TRUE,
"numeric"=pi,
"Date"=as.Date("2020-04-29", origin="1970-01-01")
)
observeEvent(input$addTypedLoop,
columns <- v$data %>% summarise_all(class) %>% gather(variable, class)
v$data <- v$data %>% add_row()
targetRow <- nrow(v$data)
for (col in columns$variable)
colClass <- (columns %>% filter(variable == col))$class
v$data <- v$data %>% mutate(!! col := ifelse(row_number() == targetRow, asTypedValue(newValues[col], colClass), !! col))
)
shinyApp(ui, server)
提前感谢您的帮助。
【问题讨论】:
【参考方案1】:在这里你连接成一个原子向量:
newValues <- c("W"="Testing...", "X"=pi, "Y"=TRUE, "Z"=as.Date("2020-04-29"))
原子向量包含相同模式的元素,所以一切都被强制转换为字符模式:
> newValues
W X Y Z
"Testing..." "3.14159265358979" "TRUE" "18381"
改用列表:
newValues <- list("W"="Testing...", "X"=pi, "Y"=TRUE, "Z"=as.Date("2020-04-29"))
(然后使用newValues[[f]]
)。
【讨论】:
斯蒂芬,谢谢!就我而言,那是树木的时刻!当我使用addLoop
选项时,您的建议已经解决了这个问题[这给了我一个可以在我的应用程序中使用的解决方案],但是 addTypedLoop 仍然将最后一列从Date
转换为double
。那里发生了什么?以上是关于在空的 tibble 中,列类型会根据添加第一行的方式而改变的主要内容,如果未能解决你的问题,请参考以下文章
是否在空的初始化程序列表(并明确指定类型)上调用 std::min 未定义的行为?
如何将网格线保留在空的 TableView Javafx 中