Reputation: 79
I'm trying to write a shiny app for pseudonymisation. It needs to receive a CSV file, let the user select which columns need to be removed, and download the data. The problem I cannot solve is why the for loop doesn't work as it does in a normal script.
Here is the code.
UI
library(shiny)
fluidPage(
titlePanel("Anonimizador"),
sidebarLayout(
sidebarPanel(
fileInput(
'file_input',
'Escolha a base de dados para anonimização',
accept = c(
'text/csv',
'text/comma-separated-values',
'.csv'
)
),
radioButtons(
"separador",
"Separador: ",
choices = c(";",",",":")
),
radioButtons(
"encoding",
"Encoding: ",
choices = c("UTF-8", "latin1")
)
),
mainPanel(
fluidRow(
dataTableOutput("table_output")
),
hr(),
fluidRow(
column(
6,
checkboxGroupInput(
"colunas",
"Selecione as colunas para anonimizar:",
choices = NULL
)
),
column(
6,
downloadButton(
'downloadData',
'Baixe a base anonimizada'
)
)
)
)
)
)
SERVER
library(shiny)
library(dplyr)
shinyServer(function(session, input, output) {
db <- reactive({
inFile <- input$file_input
if (is.null(inFile)) return(NULL)
db <- read.csv(
inFile$datapath,
header = TRUE,
sep = input$separador,
encoding = input$encoding
)
return(db)
})
output$table_output <- renderDataTable({
db <- db()
db
},
options = list(
scrollX = TRUE,
pageLength = 5
)
)
observe({
updateCheckboxGroupInput(
session,
"colunas",
"Selecione as colunas para anonimizar:",
choices = names(db())
)
})
db_anonimizado <- reactive({
db <- db()
colunas <- names(db[,input$colunas])
db_novo <- db
for (i in 1:length(colunas)) {
unicos <- data.frame(
original = unique(db[,colunas[i]]),
novo = 1:nrow(unique(db[,colunas[i]]))
)
db_novo <- left_join(db_novo, unicos, by = colunas[i])
}
db_novo$unico <- 1:nrow(db_novo)
nomes_novos <- names(db_novo[,(ncol(db_novo)-length(colunas)): ncol(db_novo)])
db_novo$indicador_anonimizado <- do.call(
paste0,
db_novo[,nomes_novos]
)
remove <- c(colunas, nomes_novos)
db_novo <- db_novo[,-which(names(db_novo) %in% remove)]
db_novo
})
output$downloadData <- downloadHandler(
filename = function() {
paste('anonimizada.csv')
},
content = function(file) {
write.csv(
db_anonimizado(),
file
)
}
)
})
If anyone could help me I'd be very grateful
Upvotes: 0
Views: 102
Reputation: 21349
You have several issues in your code.
nrow(unique(db[,colunas[i]]))
gives a NULL
for me. Perhaps length()
is better here.+1
in ncol(db_novo)-length(colunas)+1
Full code
library(shiny)
ui <- fluidPage(
titlePanel("Anonimizador"),
sidebarLayout(
sidebarPanel(
fileInput(
'file_input',
'Escolha a base de dados para anonimização',
accept = c(
'text/csv',
'text/comma-separated-values',
'.csv'
)
),
radioButtons(
"separador",
"Separador: ",
choices = c(",",";",":")
),
radioButtons(
"encoding",
"Encoding: ",
choices = c("UTF-8", "latin1")
)
),
mainPanel(
fluidRow(
dataTableOutput("table_output"), DTOutput("t1")
),
hr(),
fluidRow(
column(
6,
checkboxGroupInput(
"colunas",
"Selecione as colunas para anonimizar:",
choices = NULL
)
),
column(
6,
downloadButton(
'downloadData',
'Baixe a base anonimizada'
)
)
)
)
)
)
library(dplyr)
server <- shinyServer(function(session, input, output) {
db <- reactive({
inFile <- input$file_input
if (is.null(inFile)) return(NULL)
db <- read.csv(
inFile$datapath,
header = TRUE,
sep = input$separador,
encoding = input$encoding
)
return(db)
})
output$table_output <- renderDataTable({
db <- db()
db
},
options = list(
scrollX = TRUE,
pageLength = 5
)
)
observe({
updateCheckboxGroupInput(
session,
"colunas",
"Selecione as colunas para anonimizar:",
choices = names(db())
)
})
db_anonimizado <- reactive({
req(input$colunas,db())
db <- db()
colunas <- names(db[,input$colunas])
db_novo <- db
n <- length(input$colunas)
if (n==1) {
unicos <- data.frame(
original = unique(db[,input$colunas]),
novo1 = 1:length(unique(db[,input$colunas]))
)
names(unicos)[1] <- c(sym(input$colunas))
db_novo <- left_join(db_novo, unicos, by = names(unicos)[1])
lastcol <- ncol(db_novo)
nomes_novos <- c(names(db_novo)[lastcol])
remove <- c(input$colunas, nomes_novos)
db_novo$indicador_anonimizado <- db_novo[,c(nomes_novos)]
}else if (n>1) {
for (i in 1:n) {
unicos <- data.frame(
original = unique(db[,colunas[i]]),
novo2 = 1:length(unique(db[,colunas[i]]))
)
names(unicos)[1] <- c(sym(colunas[i]))
db_novo <- left_join(db_novo, unicos, by = colunas[i])
}
nomes_novos <- names(db_novo[,(ncol(db_novo)-length(colunas)+1): ncol(db_novo)])
remove <- c(colunas, nomes_novos)
db_novo$indicador_anonimizado <- do.call(
paste0,
db_novo[,c(nomes_novos)]
)
}
#print(nomes_novos)
db_novo$unico <- 1:nrow(db_novo)
#nomes_novos <- names(db_novo[,(ncol(db_novo)-length(colunas)): ncol(db_novo)])
# db_novo$indicador_anonimizado <- do.call(
# paste0,
# db_novo[,c(nomes_novos)]
# )
#remove <- c(colunas, nomes_novos)
db_novo <- db_novo[,-which(names(db_novo) %in% remove)]
db_novo
})
output$t1 <- renderDT({
req(db_anonimizado())
db_anonimizado()
})
output$downloadData <- downloadHandler(
filename = function() {
paste('anonimizada.csv')
},
content = function(file) {
write.csv(
db_anonimizado(),
file
)
}
)
})
shinyApp(ui, server)
Upvotes: 1