how to Wrap Text in renderTable in Shiny - r

At one point in my code, I have:
output$summaryTable <- renderTable({
createData()$summary
},align='lll')
However, createData()$summary[2,1] and createData()$summary[2,2] are both very long and thus the table has a very wide scroller. What's the best way to fix it so that it wraps?
Thanks!

if Your question is still valid, here is one solution for Your problem:
output$summaryTable <- DT::renderDataTable({
datatable(createData()$summary,
options = list(columnDefs = list(list(targets = 1,render = JS("function(data, type, row, meta) {","return type === 'display' && data.length > 10 ?","'<span title=\"' + data + '\">' + data.substr(0, 8) + '...</span>' : data;","}")))))})
if the row has more then 10 characters (data.length > 10), dataTable is going to display only 8 (data.substr(0, 8)) of them:
rowwithlongname -> rowwithl...
when you get mouse over the row then the full name is displayed

I cannot replicate your table but it seems that you will have to add some css to format the table the way you want.
You would probably have to add in your ui.r something like:
tags$head(
tags$style(
HTML("#summaryTable table tr td {word-wrap: break-word}")
)
)
I could test for validity of my answer if I could replicate your table.

Related

How to remove quotes around string using glue_sql() and sub() inside a loop?

My code sample :
fields <- data.frame(names=c("A", "B"))
variables <- c()
for (i in 1:nrow(fields)) {
variables[[i]] <- fields$names[i]
query <- glue_sql("UPDATE schema1.table1 a SET {variables } = (
SELECT {variables} FROM schema2.table2 b WHERE b.id_obs = a.id_obs)", .con = pool)
Output:
<SQL> UPDATE schema1.table1 a SET 'A' = (
SELECT 'A' FROM public.test1 b WHERE b.id_obs = a.id_obs)
<SQL> UPDATE schema1.table1 a SET 'B' = (
SELECT 'B' FROM public.test1 b WHERE b.id_obs = a.id_obs)
I'm wondering how can I remove the quotes around my variable_names (A and B) in the output ?
I tried to add query <- sub("('.*?')", variables, query) but I don't really understand the behaviour of sub() within my loop...
Could someone help me out please ?
You can use gsub instead:
query <- gsub("'", '',glue_sql("UPDATE schema1.table1 a SET {variables } = (
SELECT {variables} FROM schema2.table2 b WHERE b.id_obs = a.id_obs)", .con = pool) )

How to read fixed width files using Spark in R

I need to read a 10GB fixed width file to a dataframe. How can I do it using Spark in R?
Suppose my text data is the following:
text <- c("0001BRAjonh ",
"0002USAmarina ",
"0003GBPcharles")
I want the 4 first characters to be associated to the column "ID" of a data frame; from character 5-7 would be associated to a column "Country"; and from character 8-14 to be associated to a column "Name"
I would use function read.fwf if the dataset was small, but that is not the case.
I can read the file as a text file using sparklyr::spark_read_text function. But I don't know how to attribute the values of the file to a data frame properly.
EDIT: Forgot to say substring starts at 1 and array starts at 0, because reasons.
Going through and adding the code I talked about in the column above.
The process is dynamic and is based off a Hive table called Input_Table. The table has 5 columns: Table_Name, Column_Name, Column_Ordinal_Position, Column_Start, and Column_Length. It is external so any user can change, drop, and remove any file into the folder location. I quickly built this from scratch to not take actual code, does everything make sense?
#Call Input DataFrame and the Hive Table. For hive table we make sure to only take correct column as well as the columns in correct order.
val inputDF = spark.read.format(recordFormat).option("header","false").load(folderLocation + "/" + tableName + "." + tableFormat).rdd.toDF("Odd_Long_Name")
val inputSchemaDF = spark.sql("select * from Input_Table where Table_Name = '" + tableName + "'").sort($"Column_Ordinal_Position")
#Build all the arrays from the columns, rdd to map to collect changes a dataframe col to a array of strings. In this format I can iterator through the column.
val columnNameArray = inputSchemaDF.selectExpr("Column_Name").rdd.map(x=>x.mkString).collect
val columnStartArray = inputSchemaDF.selectExpr("Column_Start_Position").rdd.map(x=>x.mkString).collect
val columnLengthArray = inputSchemaDF.selectExpr("Column_Length").rdd.map(x=>x.mkString).collect
#Make the iteraros as well as other variables that are meant to be overwritten
var columnAllocationIterator = 1
var localCommand = ""
var commandArray = Array("")
#Loop as there are as many columns in input table
while (columnAllocationIterator <= columnNameArray.length) {
#overwrite the string command with the new command, thought odd long name was too accurate to not place into the code
localCommand = "substring(Odd_Long_Name, " + columnStartArray(columnAllocationIterator-1) + ", " + columnLengthArray(columnAllocationIterator-1) + ") as " + columnNameArray(columnAllocationIterator-1)
#If the code is running the first time it overwrites the command array, else it just appends
if (columnAllocationIterator==1) {
commandArray = Array(localCommand)
} else {
commandArray = commandArray ++ Array(localCommand)
}
#I really like iterating my iterators like this
columnAllocationIterator = columnAllocationIterator + 1
}
#Run all elements of the string array indepently against the table
val finalDF = inputDF.selectExpr(commandArray:_*)

Shiny conditionalPanel conditions based on NULL values in R?

I am writing a Shiny application that will query a database a few times. The queries may take some time, so I am using actionButton to allow the user to control when they are started.
The general flow of the application is:
User loads page, pushes button to load in available choices from the database.
User selects a row from the available choices, and then kicks off a larger query that will take longer.
When the query is done, the user will get nice visualizations and other such things.
I know that you can allow the user to select rows from a DataTable using the selection option, and I am currently using the development build so that single-selection can be enabled. My problem is figuring out how to hide certain conditional panels until the user has made a choice. As far as I can tell, the value of the choice is stored in input$[data frame name]_rows_selected. But, until the values are selected, this value is either NULL, or does not exist.
I cannot figure out how to pass to the condition argument of conditionalPanel() a condition which reflects the internal R logic. I've written a minimal working example below which shows the behavior to which I'm referring.
library(shiny)
library(DT)
# Create sample data
df_sample_data <- data.frame(name = c("John Smith","Jane Cochran","Belle Ralston","Quincy Darcelio"),
color = c("Red","Blue","Red","Green"),
age = c(25,52,31,29))
ui <-
fluidPage(
titlePanel("The Title!"),
sidebarPanel(
h1("Load Data"),
actionButton("load_data","Load Data"),
br(),
conditionalPanel(
h1("Do Thing"),
actionButton("do_thing","Do Thing"),
condition = "input.df_data_rows_selected !== undefined")
),
mainPanel(
dataTableOutput("df_data"),
conditionalPanel(
tableOutput("row_selected"),
condition = "input.df_data_rows_selected !== undefined")
)
)
server <-
function(input, output) {
# This function loads the data (in reality it is a server operation)
uFunc_ReactiveDataLoad <- eventReactive(eventExpr = input$load_data,valueExpr = {
df_data <- df_sample_data
return(list(display_table = datatable(data = df_data[c("name","age")],
options = list(dom = "tip"),
filter = "top",
selection = "single",
colnames = c("Person Name" = "name",
"Person Age" = "age")),
data_table = df_data))
})
output$df_data <- renderDataTable(expr = uFunc_ReactiveDataLoad()$display_table)
output$row_selected <- renderTable(expr = uFunc_ReactiveDataLoad()$data_table[input$df_data_rows_selected,])
}
shinyApp(ui = ui, server = server)
In the current setup, which uses input.df_data_rows_selected !== undefined, the panels are hidden until the data is loaded using the first actionButton. But, I need them to remain hidden unless the user has selected a row. I have tried other things such as:
input.df_data_rows_selected !== null
input.df_data_rows_selected !== 'null'
input.df_data_rows_selected !== ''
input.df_data_rows_selected !== 'NULL'
...and so on, but I have had no luck. How does the NULL value in R get represented in the JavaScript used for the condition argument to conditionalPanel()?
condition = "(typeof input.df_data_rows_selected !== 'undefined' && input.df_data_rows_selected.length > 0)" for both entries seems to work.
condition = "(typeof input.df_data_rows_selected === null")
If anyone is stumbling upon this issue a few years later...

Shiny: BigQuery Fails when user selects "All" value

I am trying to use a BigQuery query to populate plots in Shiny. The query includes input values from the ui using selectInput. If the user selects a value that exists in the DB, such as year is 2014, the query works correctly, however, I would like the user to also be able to select "All." "All" should be a selection of all values, however, I am not sure how to express that in the query using selectInput.
server.r
data1 <- eventReactive(input$do_sql, {
bqr_auth(token = NULL, new_user = FALSE, verbose = FALSE)
query = paste('select month, event, partner_name, sum(f0_) from [dataset.table] where year =',input$year1,' and partner_name = \"',input$partner_name,'\"
GROUP by 1,2,3
ORDER by 1 asc
LIMIT 10000', sep="")
bqr_query(projectId, datasetId, query, maxResults =2000)
})
ui.r
(
selectInput("year1",
"Year:",
c("All",2014,2015
))
),
(
selectInput("partner_name",
"Partner:",
c("All",
unique(as.character(data5$partner_name))))
You should slightly change the query you are constructing
So, currently you have
SELECT month, event, partner_name, SUM(f0_)
FROM [dataset.table]
WHERE year = selected_year
AND partner_name = "selected_partner_name"
GROUP BY 1,2,3
ORDER BY 1 ASC
LIMIT 10000
with respectively:
selected_year --> input$year1
selected_partner_name --> input$partner_name
Instead, you should construct below query
SELECT month, event, partner_name, SUM(f0_)
FROM [dataset.table]
WHERE (year = selected_year OR "selected_year" = "All")
AND (partner_name = "selected_partner_name" OR "selected_partner_name" = "All")
GROUP BY 1,2,3
ORDER BY 1 ASC
LIMIT 10000
I am not shiny user at all - so excuse my syntax - below is just my
guess with regard of implementing above suggestion
query = paste('SELECT month, event, partner_name, sum(f0_)
FROM [dataset.table]
WHERE (year =',input$year1,' OR "All" ="',input$year1,'")
AND (partner_name = \"',input$partner_name,'\" OR "All" = \"',input$partner_name,'\")
GROUP by 1,2,3
ORDER by 1 asc
LIMIT 10000', sep="")
Mikhail's solution worked perfectly for character variables, but numerics didn't work correctly. I decided to use a character date range instead of the year numeric I originally used. Thanks.

sql query to fix phone number problem in table

I have a table which contains a phone number column. There is no restrictions on how to enter the phone numbers. Currently the phone numbers are in the following format
123-456-7890
(123)-456-7890
1234567890
I would like to update the table and bring all phone numbers in 123-456-7890 format. I have over 20k records. Can I do that using SQL Query or I have to use regular expression in ASP or PHP?
Edit: Note best answer is for modified question, with phone number (123)-456-78790 changed to (123)456-7890
If they are strictly in one of those 3 formats, you can do it in SQL easy enough by using SUBSTRING and testing the LEN of each item.
If there are other formats, I'd suggest doing this in a language that is better at text-manipulation, such as .net.
Edit to add:
Given your comment that it'll only be those 3 formats for now, you can do this:
declare #t table (x varchar(20))
insert into #t
select '123-456-7890'
union select '(123)456-7890'
union select '1234567890'
select
case
when len(x) = 10 then
substring(x, 1, 3) + '-' + substring(x, 4, 3) + '-' + substring(x, 7, 4)
when len(x) = 13 then
substring(x, 2, 3) + '-' + substring(x, 6, 8)
else x
end
from #t
This will work:
First replace the parentheses and hyphens, then add them back in.
DECLARE #Number varchar(25)
SELECT #Number = '(123)-456-7890'
SELECT SUBSTRING(REPLACE(REPLACE(REPLACE(#Number, '(', ''), ')', ''), '-', ''), 1, 3)
+ '-'
+ SUBSTRING(REPLACE(REPLACE(REPLACE(#Number, '(', ''), ')', ''), '-', ''), 4, 3)
+ '-'
+ SUBSTRING(REPLACE(REPLACE(REPLACE(#Number, '(', ''), ')', ''), '-', ''), 7, 4)
Note
You could create a scalar function to replace all the hyphens and parentheses... It would be more readable then:
DECLARE #Number varchar(25)
SELECT #Number = '(123)-456-7890'
SELECT SUBSTRING(StripCharacters(#Number), 1, 3)
+ '-'
+ SUBSTRING(StripCharacters(#Number), 4, 3)
+ '-'
+ SUBSTRING(StripCharacters(#Number), 7, 4)
Succinct and without temp tables:
UPDATE Phones
SET phone =
SUBSTRING(REPLACE(REPLACE(REPLACE(phone,'-',''),')',''),'(',''),1,3) + '-'
+ SUBSTRING(REPLACE(REPLACE(REPLACE(phone,'-',''),')',''),'(',''),4,3) + '-'
+ SUBSTRING(REPLACE(REPLACE(REPLACE(phone,'-',''),')',''),'(',''),7,4)
Here is a great example:
Shows how to create User Defined Functions, custom formatting function for telephone numbers in TSQL
I would load every phone number and strip them.
So remove all periods, commas, hyphens, - basically anything that isn't a number.
Then reinsert them in the format you're looking for.
you can do this through a query, or server side language.
If you only have 20K records then just go with whatever is easier for you. Personally, I would pull all the data and then reinsert it using a server side language. PHP, ASP, or SQL it doesn't really matter if this is a one time thing. Just be sure to set up some formatting restrictions on new inserts though.
Look at this quick example:
CREATE TABLE #temp
(
phonenumber VARCHAR(15)
)
INSERT INTO #temp
( phonenumber )
VALUES ( '555-578-5899'
INSERT INTO #temp
( phonenumber )
VALUES ( '(555)-896-3269' )
INSERT INTO #temp
( phonenumber )
VALUES ( '123-456-2129')
update #temp
set phonenumber=replace(phonenumber,'(','')
update #temp
set phonenumber=replace(phonenumber,')','')
update #temp
set phonenumber=replace(phonenumber,'-','')
-- That will eliminate all (,- and ) from the table
update #temp
set phonenumber=left(phonenumber,3)+'-'+substring(phonenumber,4,3)
+'-'+right(phonenumber,4)
SELECT * FROM #temp
DROP TABLE #temp

Resources