using 'input$entry' inside paste0 for variable length entry[1:n] - r

I have a clunky block of shiny code on server.R side that I feel R syntax ought to allow me make one or two lines and simultaneously more flexible with some kind of lapply or do.call line
if(input$parVary == "area" && as.numeric(input$nTraces) > 3 )
{
area <- c(input$area, input$area2, input$area3, input$area4)
} else if(input$parVary == "area" && as.numeric(input$nTraces) > 2 )
{
area <- c(input$area, input$area2, input$area3)
} else if(input$parVary == "area" && as.numeric(input$nTraces) > 1 )
{
area <- c(input$area, input$area2)
} else
{
area <- input$area
}
But I have spent a day and about a billion different combos of lapply, do.calls, reactive, get, c, and observes around
paste0('input$area', 1:as.numeric(input$nTraces))
I just can't seem to find the right combination or figure out the reactive concept I'm missing. It -seems- to be related to the code not ever including individual input$area1, input$area2, etc... explicit text anywhere in the code?

I spoke a little too soon in comment above. My specific code ended up needing conditional to handle the list versus single value case. But #NicE answer is one I was looking for. Five sections like
if(input$parVary == "area" && as.numeric(input$nTraces) > 1 )
{
area <- lapply(paste0("area",1:as.numeric(input$nTraces)),function(x) input[[x]])
} else
{
area <- input$area1
}
teamed with later
mySolution <- list()
if(input$nTraces =='1')
{
mySolution <- solveCalc(dat=dat,tox=tox,area=area,temp=temp,model=modelIn)
} else
{
mySolution <- switch(input$parVary,
"model" = lapply(modelIn,solveCalc,dat=dat,tox=tox,area=area,temp=temp),
"temp" = lapply(temp,solveCalc,dat=dat,tox=tox,area=area,model=modelIn),
"tox" = lapply(tox,solveCalc,dat=dat,temp=temp,area=area,model=modelIn),
"Vt" = lapply(dat,solveCalc,tox=tox,temp=temp,area=area,model=modelIn),
"area" = lapply(area,solveCalc,dat=dat,tox=tox,temp=temp,model=modelIn)
)
}
Got me just what I wanted.

Related

why c() does not working in this recursive function in R?

enter image description here
I know there exists function 'unique' which works similar to what I want to make, but I want to make this function.
I want this function finally returns 'result' which contains unique elements of input vector.
But I don't know why this function's result is totally different from my expect.
Why c which is to combine before result and new unique element is not working.
Please tell me how to fix my code.
Thank you.
I think what you expect might be something like below, where result should be an argument of m_uni:
m_uni <- function(x,result = c()) {
if (class(x)=='numeric'| class(x)=='character') {
if (length(x) <= 1){
return(result)
} else {
if (x[length(x)] %in% result) {
x <- x[-length(x)]
m_uni(x,result)
} else {
result <- c(result,x[length(x)])
x <- x[-length(x)]
m_uni(x,result)
}
}
} else {
return('This function only gets numeric or character vector')
}
}
such that
> m_uni(x)
[1] 0 4 5 -2

if/else statement evaluating only else statement

Disclaimer: This is a question regarding an assignment for a Coursera course.
I'm having trouble coming up with a way to create a new column that differentiates between weekdays and weekends in my data set. I'm using a nested if/else statement within a for loop. The problem is the output makes every row 'weekday'. Does anyone see something glaringly wrong with my code? My end goal is to create a new factor variable that is either "weekend" or "weekday."
df4 <- mutate(df4, day = weekdays(df4$date))
for (i in df4$day) {
if(i %in% c("Saturday",'Sunday')) {
df4$day_type <- 'weekend'
} else {
df4$day_type <- 'weekday'
}
}
I modify a little bit of your code .(see below)
for (i in 1 : dim(df4)[1]) {
if(df4$day[i] %in% c('Saturday','Sunday')) {
df4$day_type[i] <- 'weekend'
} else {
df4$day_type[i] <- 'weekday'
}
}

R: Collect intermediate output of recursive function

I have a recursive function that uses the output of the previous call as the input of the next call:
recurse_foo = function(input) {
if(identical(input, character(0))) return(NULL)
else {
uu = get_incremental_output(input) ## <-- interested in collecting this
return(recurse_foo(uu))
}
}
As is evident, the terminal output is not very interesting, and I am interested in collecting the intermediate output, but I cannot imagine that growing a global list or any other side effect would be elegant (which is the only thing I can think of).
Any other abstractions that might be useful here?
Thanks.
Specific example:
final_countdown = function(input) {
if (input/2 < 1) return(NULL)
else {
uu = input/2 # <-- interested in collecting this
print(uu)
return(final_countdown(uu))
}
}
final_countdown(100)
In this case, I am interested in collecting the sequence of uus that are printed.
This is a solution, if all intermediate outputs are of the same type:
final_countdown = function(input) {
if (input/2 < 1) return(NA)
else {
c(input, final_countdown(input/2))
}
}

Combining a for loop with meta characters

Im writing a for loop that checks whether values in a particular column match a predefined list.
So it's kind of like this:
money <- read.csv2("money.csv", header = T)
#set counter
count_financial = 1
#set list
financial_items <- c("bank", "ABN Amro")
for (i in 1:nrow(money)) {
if(money$Description[i] in financial_items ) {
count_financial = count_financial + 1
}
}
It's working for now but I actually want to tweak it a little and use metacharacters. So I cant only find items which say "Bank" or "ABN Amro" but also lines which "bank cost" or "ABN Amro transaction".
Any thoughts on how I can do this?
Try:
length(financial_items %in% money$Description)
But if you are intent on using the loop:
for (i in 1:nrow(money)) {
if(money$Description[i] %in% financial_items ) {
count_financial = count_financial + 1
}
}
Update:
Upon rereading the question, I think you are looking for:
length(grep("bank|abn amro", money$Description, ignore.case=TRUE))
You could try
filtered <- money[grep("bank|ABN Amro",money$Description,ignore.case=TRUE),]
count_financial <- nrow(filtered)

R -- screening Excel rows according to characteristics of multiple cells

I am trying to eliminate all rows in excel that have he following features:
First column is an integer
Second column begins with an integer
Third column is empty
The code I have written appears to run indefinitely. CAS.MULT is the name of my dataframe.
for (i in 1:nrow(CAS.MULT)) {
testInteger <- function(x) {
test <- all.equal(x, as.integer(x), check.attributes = FALSE)
if (test == TRUE) {
return (TRUE)
}
else {
return (FALSE)
}
}
if (testInteger(as.integer(CAS.MULT[i,1])) == TRUE) {
if (testInteger(as.integer(substring(CAS.MULT[i,2],1,1))) == TRUE) {
if (CAS.MULT[i,3] == '') {
CAS.MULT <- data.frame(CAS.MULT[-i,])
}
}
}
}
You should be very wary of deleting rows within a for loop, if often leads to undesired behavior. There are a number of ways you could handle this. For instance, you can flag the rows for deletion and then delete them after.
Another thing I noticed is that you are converting your columns to integers before passing them to your function to test if they are integers, so you will be incorrectly returning true for all values passed to the function.
Maybe something like this would work (without a reproducible example it's hard to say if it will work or not):
toDelete <- numeric(0)
for (i in 1:nrow(CAS.MULT)) {
testInteger <- function(x) {
test <- all.equal(x, as.integer(x), check.attributes = FALSE)
if (test == TRUE) {
return (TRUE)
}
else {
return (FALSE)
}
}
if (testInteger(CAS.MULT[i,1]) == TRUE) {
if (testInteger(substring(CAS.MULT[i,2],1,1)) == TRUE) {
if (CAS.MULT[i,3] == '') {
toDelete <- c(toDelete, i)
}
}
}
}
CAS.MULT <- CAS.MULT[-1*toDelete,]
Hard to be sure without testing my code on your data, but this might work. Instead of a loop, the code below uses logical indexing based on the conditions you specified in your question. This is vectorized (meaning it operates on the entire data frame at once, rather than by row) and is much faster than looping row by row:
CAS.MULT.screened = CAS.MULT[!(CAS.MULT[,1] %% 1 == 0 |
as.numeric(substring(CAS.MULT[,2],1,1)) %% 1 == 0 |
CAS.MULT[,3] == ""), ]
For more on checking whether a value is an integer, see this SO question.
One other thing: Just for future reference, for efficiency you should define your function outside the loop, rather than recreating the function every time through the loop.

Resources