Skip to content

Commit

Permalink
News 2025.02.19-1
Browse files Browse the repository at this point in the history
  • Loading branch information
lgschuck committed Feb 20, 2025
1 parent 83b03f8 commit 4f7d25c
Show file tree
Hide file tree
Showing 20 changed files with 424 additions and 175 deletions.
12 changes: 12 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,21 @@ importFrom(data.table,copy)
importFrom(data.table,fcase)
importFrom(data.table,fread)
importFrom(data.table,fwrite)
importFrom(data.table,hour)
importFrom(data.table,mday)
importFrom(data.table,minute)
importFrom(data.table,month)
importFrom(data.table,quarter)
importFrom(data.table,second)
importFrom(data.table,setDT)
importFrom(data.table,setcolorder)
importFrom(data.table,setnames)
importFrom(data.table,setorderv)
importFrom(data.table,shift)
importFrom(data.table,wday)
importFrom(data.table,week)
importFrom(data.table,yday)
importFrom(data.table,year)
importFrom(dplyr,arrange)
importFrom(dplyr,filter)
importFrom(dplyr,mutate)
Expand Down
18 changes: 18 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,24 @@ editor_options:

6 - Models: linear model, logistic regression, Kmeans, Trees

## 2025.02.19-1

Highlights: New **Calculate Cols** module, better internal control over changes in datasets and many small visual improvements

### Improvements

1 - New **Calculate Cols** module: allow create new variable by applying a function

2 - **Convert Cols, Data Overview, Filter Rows, Order Cols, Order Rows, Rename Cols and Select Cols** modules and **spada_server.R**: now uses data.table::copy to return changes in dataset properly and maintaining the correct update in reactives (problem probably caused by changes by reference in data.table). Removed all triggers (df_trigger reactiValues) used before.

3 - **Data Overview, Navbar_df_info and Sidebar** modules: removed stylling code (passed to spada_themes).

4 - **spada_ui.R**: some new cards (Data Page: metadata and Overview) for better look and Active dataset navbar item now shows only the name (with out 'Active dataset' prefix)

5 - **spada_themes**: new mini-btn class to format small buttons in Sidebar and Navbar Df Info modules

6 - **utils.R**: new objects with functions to use in Calculate Cols module.

## 2025.02.16-1

Highlights: New **Darkly** theme and new dependencie: **sass** package.
Expand Down
101 changes: 101 additions & 0 deletions R/calculate_cols_module.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@


# ui --------------------------------------------------------------------------
calculate_cols_ui <- function(id) {
ns <- NS(id)

card(
card_header('Apply Function', class = 'mini-header'),
card_body(
uiOutput(ns('ui_var_sel')),
textInput(ns('txt_new_name'), 'New name'),
uiOutput(ns('ui_fun_sel'))
),
card_footer(btn_task(
ns('btn_apply_fun'), 'Apply', icon('check')
))
)
}

# server ----------------------------------------------------------------------
calculate_cols_server <- function(id, input_df) {
moduleServer(id, function(input, output, session) {
ns <- NS(id)

# Reactive to get column names
df_names <- reactive(input_df() |> names())

df <- reactiveValues()
observe({
df$df_active <- input_df()
})

# render variables to sel -------------------------------------------------
output$ui_var_sel <- renderUI({
selectInput(ns('vars_sel'), 'Variable', c('', df_names()))
})

# suggest name for new variable -------------------------------------------
observe({
req(input$vars_sel)
updateTextInput(session, 'txt_new_name',
value = paste0(input$vars_sel, '_new'))
}) |> bindEvent(input$vars_sel)

# render functions choices ------------------------------------------------
selected_var_type <- reactive({
req(input$vars_sel)
obj_type(df$df_active[[input$vars_sel]])
})


output$ui_fun_sel <- renderUI({
req(input$vars_sel)
if (selected_var_type() == 'numeric') {
selectInput(ns('fun'), 'Choose a function', choices = math_funs)
} else if (selected_var_type() == 'char'){
selectInput(ns('fun'), 'Choose a function', choices = char_funs)
} else if (selected_var_type() == 'date'){
selectInput(ns('fun'), 'Choose a function', choices = date_funs)
} else if (selected_var_type() == 'logical'){
selectInput(ns('fun'), 'Choose a function', choices = logical_funs)
} else if (selected_var_type() == 'factor'){
selectInput(ns('fun'), 'Choose a function', choices = factor_funs)
} else if (selected_var_type() == 'complex'){
selectInput(ns('fun'), 'Choose a function', choices = complex_funs)
} else {
selectInput(ns('fun'), 'Choose a function', choices = character(0))
}
})

observe({
req(input$vars_sel, input$txt_new_name, df$df_active, input$fun)
if (input$vars_sel |> length() == 0) {
msg('Select at least one variable')
} else {
if (is_valid_name(input$txt_new_name) &&
input$txt_new_name %notin% df_names()) {

temp <- copy(df$df_active)

temp[, new_var := fun(var1), env = list(
new_var = input$txt_new_name,
fun = input$fun,
var1 = input$vars_sel
)]

df$df_active <- copy(temp)
rm(temp)

msg('Apply function: OK')

} else {
msg_error('New name is not valid or already in use')
}

}
}) |> bindEvent(input$btn_apply_fun)

return(list(df_calculate_cols = reactive(df$df_active)))
})
}
18 changes: 9 additions & 9 deletions R/convert_cols_module.R
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ convert_cols_ui <- function(id) {
}

# server ----------------------------------------------------------------------
convert_cols_server <- function(id, input_df, input_df_trigger) {
convert_cols_server <- function(id, input_df) {
moduleServer(id, function(input, output, session) {
ns <- NS(id)

Expand All @@ -53,7 +53,6 @@ convert_cols_server <- function(id, input_df, input_df_trigger) {
df <- reactiveValues()
observe({
df$df_active <- input_df()
df$df_trigger <- input_df_trigger()
})

output$ui_var_sel <- renderUI(
Expand All @@ -78,13 +77,12 @@ convert_cols_server <- function(id, input_df, input_df_trigger) {
# sample to preview conversion
preview_sample_trigger <- reactiveVal(1)
preview_sample <- reactive({
preview_sample_trigger()
if(nrow(df$df_active) < 8) {
rep(TRUE, nrow(df$df_active))
} else {
sample(nrow(df$df_active), 8, replace = F)
}
})
}) |> bindEvent(preview_sample_trigger())

# update sample in button click
observe({
Expand Down Expand Up @@ -127,24 +125,26 @@ convert_cols_server <- function(id, input_df, input_df_trigger) {
}
})

# apply conversions -------------------------------------------------------
observe({
if(input$vars_sel == '' | input$sel_format == ''){
msg('Choose a variable and a new format')
} else {

df$df_active[, input$vars_sel :=
temp <- copy(df$df_active)
temp[, input$vars_sel :=
convert(var1,
type = input$sel_format,
date_format = input$sel_date_formats,
date_origin = input$sel_date_origin),
env = list(var1 = input$vars_sel)]

df$df_active <- copy(temp)
rm(temp)
msg('Conversion applied')
}

df$df_trigger <- df$df_trigger + 1
}) |> bindEvent(input$btn_apply)

return(list(df_convert_cols = reactive(df$df_active),
df_convert_cols_trigger = reactive(df$df_trigger)))
return(list(df_convert_cols = reactive(df$df_active)))
})
}
30 changes: 12 additions & 18 deletions R/data_overview_module.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,29 @@
# ui --------------------------------------------------------------------------
data_overview_ui <- function(id) {
ns <- NS(id)
tagList(
card_body(gt_output(ns('gt')),
style = "margin-top: -24px !important;
margin-bottom: -24px !important;
padding-top: -24px !important;
padding-bottom: -24px !important;
"),
fluidRow(
column(2, numericInput(ns('size_sample'), 'Number of rows', 100, 100, 1e4, 100)),
column(2, radioGroupButtons(
ns('radio_sample'), 'Show',
c('First rows' = 'first', 'Sample' = 'sample'),
size = 'sm', individual = T)),
style = "margin-top: -16px !important; margin-bottom: -16px !important;"
),
card(
card_body(gt_output(ns('gt'))),
card_footer(
fluidRow(
column(2, numericInput(ns('size_sample'), 'Number of rows', 500, 0, 1e4, 500)),
column(2, radioGroupButtons(
ns('radio_sample'), 'Show',
c('First rows' = 'first', 'Sample' = 'sample'),
size = 'sm', individual = T))
)
)
)
}

# server ----------------------------------------------------------------------
data_overview_server <- function(id, df, triggers) {
data_overview_server <- function(id, df) {
moduleServer(id, function(input, output, session) {

output$gt <- render_gt({
req(input$size_sample)

validate(need(input$size_sample > 0, 'Number of rows must be > 0'))

triggers()

n_show <- max(1, input$size_sample)
n_show <- min(n_show, nrow(df()))

Expand Down
42 changes: 21 additions & 21 deletions R/filter_rows_module.R
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,7 @@ filter_rows_server <- function(id, input_df) {
ns <- NS(id)

# Reactive to get column names
df_names <- reactive({
req(input_df())
input_df() |> names()
})
df_names <- reactive(input_df() |> names())

# Store active dataset
df <- reactiveValues()
Expand Down Expand Up @@ -243,6 +240,7 @@ filter_rows_server <- function(id, input_df) {
# apply btn filter rows ---------------------------------------------------
observe({

temp <- copy(df$df_active)
# filter events for one variable ----------------------------------------
if(input$filter_type == 'one'){
# test if var and operator were informed
Expand Down Expand Up @@ -291,20 +289,20 @@ filter_rows_server <- function(id, input_df) {
# pass values to filter function
if (input$one_var_operator %in%
c(na_operators, logical_operators, outlier_operators)){
df$df_active <- filter_rows(df$df_active,
input$one_var_sel,
input$one_var_operator,
NULL)
temp <- filter_rows(temp,
input$one_var_sel,
input$one_var_operator,
NULL)
msg('Filter rows: OK')
} else if(value_temp$len > 1 & input$one_var_operator %in%
c(equal_operators, compare_operators)){
msg('Operator requires value of length 1')
return()
} else {
df$df_active <- filter_rows(df$df_active,
input$one_var_sel,
input$one_var_operator,
value_temp$value_temp)
temp <- filter_rows(temp,
input$one_var_sel,
input$one_var_operator,
value_temp$value_temp)
msg('Filter rows: OK')
}

Expand Down Expand Up @@ -334,12 +332,14 @@ filter_rows_server <- function(id, input_df) {
} else if(!isTruthy(input$two_var_operator)){
msg_error('Choose an operator')
return()
} else if(df$df_active[[input$two_var_sel1]] |> obj_type() !=
df$df_active[[input$two_var_sel2]] |> obj_type()){
} else if(temp[[input$two_var_sel1]] |> obj_type() !=
temp[[input$two_var_sel2]] |> obj_type()){
msg('Variables must be of the same type')
} else {
df$df_active <- filter_rows_2vars(
df$df_active, input$two_var_sel1, input$two_var_sel2, input$two_var_operator)
temp <- filter_rows_2vars(temp,
input$two_var_sel1,
input$two_var_sel2,
input$two_var_operator)
msg('Filter rows: OK')
}

Expand All @@ -351,7 +351,7 @@ filter_rows_server <- function(id, input_df) {
!between(input$n_rows, 1, nrow_df_active())){
msg_error(paste('Number of rows must be between 1 and', nrow_df_active()))
} else {
df$df_active <- df$df_active[
temp <- temp[
sample(1:nrow_df_active(),
input$n_rows,
replace = input$x_sample_replace), ]
Expand All @@ -360,18 +360,18 @@ filter_rows_server <- function(id, input_df) {
}

} else if(input$sample_type == 'percent'){
df$df_active <- df$df_active[
temp <- temp[
sample(1:nrow_df_active(),
input$sample_size/100 * nrow_df_active(),
replace = input$x_sample_replace), ]

msg('Filter rows: OK')
}

}
df$df_active <- copy(temp)
rm(temp)
}) |> bindEvent(input$btn_filter)

return(list(df_filter_rows = reactive(df$df_active),
btn_filter_rows = reactive(input$btn_filter)))
return(list(df_filter_rows = reactive(df$df_active)))
})
}
9 changes: 3 additions & 6 deletions R/navbar_df_info_module.R
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,9 @@ navbar_df_info_server <- function(id, input_metadata, app_session) {
),
p("Columns with NA's:", input_metadata()$n_nas),
p('Size (MB):', (input_metadata()$size)),
btn_task(ns('df_btn_overview'), '', bs_icon('search'),
style = 'padding: 5px 10px;'),
btn_task(ns('df_btn_change'), '', bs_icon('shuffle'),
style = 'padding: 5px 10px;'),
btn_task(ns('df_btn_explore'), '', bs_icon('bar-chart-line'),
style = 'padding: 5px 10px;')
actionButton(ns('df_btn_overview'), '', icon('magnifying-glass'), class = 'mini-btn'),
actionButton(ns('df_btn_change'), '', icon('shuffle'), class = 'mini-btn'),
actionButton(ns('df_btn_explore'), '', icon('chart-simple'), class = 'mini-btn')
)
})

Expand Down
Loading

0 comments on commit 4f7d25c

Please sign in to comment.