function generated dataframe with colnames - r

I am trying to create a function that generates a data frame and add the colnames programmatically.
x is a vector
foo <- function(x){
dfoo <- data.frame(Mts = 1:12)
for (i in 1:length(x)){
dfoo[i + 1] <- 1:12*i
}
colnames(dfoo) <- c("Months", paste(x, "BAR" sep = " "))
return(dfoo)
}
but it is throwing this error Error: unexpected '}' in "}"

That is because you are missing a comma in this line inside the paste
function between "BAR" and sep:
c("Months", paste(x, "BAR" sep = " "))
It should be:
c("Months", paste(x, "BAR",sep = " "))

Related

Calling sep=" " inside the function

So, I want to make an argument sep = " " work in do.call(paste) inside this.
fun <- function(x, sep=" "){
stopifnot(is.list(x))
k <- length(x)
n <- lengths(x)
stopifnot(length(unique(n))==1)
do.call(paste, c(x, sep))
}
Unfortunately, this one doesn't work and I can't find any similar topic.
Thanks for help :)
I think you maybe need sep = sep within do.call, since the lhs sep is for paste, while rhs sep is the input argument of function fun, i.e.,
fun <- function(x, sep=" "){
stopifnot(is.list(x))
k <- length(x)
n <- lengths(x)
stopifnot(length(unique(n))==1)
do.call(paste, c(x, list(sep=sep)))
}
Example
> fun(as.list(seq(3)),"-")
[1] "1-2-3"

R copy text from function output with for loop to clipboard

I've written a little function that helps renaming columns by looping through each variable and pasting various punctuation around it so that text is sent to the console. This can then be copied into my script and rename variables as required. This is the function:
library(tidyverse)
tidy_rename <- function (df) {
df_name <- deparse(substitute(df))
names(df) <- tolower(names(df))
cat(paste(df_name, " <- ", paste(df_name, "%>%\n\t rename(")))
for (i in names(df)) {
cat(paste("\t\t", paste(paste("=", paste(paste('"', i), '"'))), ","), sep="\n")
}
writeLines(")"
)
}
If I use this on a dataset:
test_df <- data.frame("VarIable 1" = c(1), "sizrd" = c(1), "dat 1" = c(1),
"x-cord" = c(1), "y-crf" = c(1), "aGe" = c(1), check.names=F)
tidy_rename(test_df)
which gives the following which can be copied and pasted into script:
test_df <- test_df %>%
rename( = " variable 1 " ,
= " sizrd " ,
= " dat 1 " ,
= " x-cord " ,
= " y-crf " ,
= " age " ,
)
What I would like is to automatically copy this output to the clipboard within the function. I'm not sure how to use writeClipboard around the forloop. This doesn't work:
tidy_rename <- function (df) {
df_name <- deparse(substitute(df))
names(df) <- tolower(names(df))
writeClipboard(
cat(paste(df_name, " <- ", paste(df_name, "%>%\n\t rename(")))
for (i in names(df)) {
cat(paste("\t\t", paste(paste("=", paste(paste('"', i), '"'))), ","), sep="\n")
}
writeLines(")"
)
)
}
Any suggestions please?
Expanding on my comment to eliminate any confusion.
A method or suggestion is to store the string in a variable, which can then be output in the end. Note from the value of cat(...) is NULL (it doesnt return the string). This requires 2 variables, lets call them str and newstr. I'll let str store the entire string that you want to copy, and newstr store the current string that is output by cat(...).
tidy_rename <- function (df) {
df_name <- deparse(substitute(df))
names(df) <- tolower(names(df))
str <- paste(df_name, " <- ", paste(df_name, "%>%\n\t rename("))
cat(str)
for (i in names(df)) {
#Store variable at each iteration and expand str. Output newstr.
newstr <- paste("\t\t", paste(paste("=", paste(paste('"', i), '"'))), ",")
str <- paste(str, newstr, sep = "\n")
cat(newstr, sep="\n")
}
newstr <- ")"
str <- paste0(str, newstr)
cat(newstr)
writeClipboard(str)
}
Note how the output is stored in str at each iteration but newstr is output.
As a side note i suggest that OP checks out the collapse argument of paste (alternatively paste0). I don't have the full overview, but it seems like this could eliminate 2 - 3 calls to paste if the strings were collapsed within one of the function calls.

R paste function repeats first argument for each word

Below is a code snippet written for writing the messages. But im not getting why the output prints the way below. Expected output is also given. I first thought the txt is a list type. But it is a character variable
writetext<-function(...){
arguments <- list(...)
if (length(arguments)>0){
txt<- paste(arguments)
if (length(txt)==0) return()
strtime <- format(Sys.time(),"%I:%M:%S%p")
txt <- paste(strtime,txt)
message(txt)
}
}
writetext("abc","efg")
01:05:13PM abc01:05:13PM efg
Expected :
01:05:13PM abcefg
You could use paste0(txt, collapse = "") :
writetext <- function(...) {
arguments <- list(...)
if (length(arguments) > 0) {
txt <- paste(arguments)
if (length(txt) == 0) return()
strtime <- format(Sys.time(), "%I:%M:%S%p")
txt <- paste(strtime, paste0(txt, collapse = ""))
message(txt)
}
}
writetext("abc", "efg")
# 07:13:45PM abcefg

How to create a custom write.table function?

I can use write.table function to create an output data from a data.frame:
> write.table(head(cars), sep = "|", row.names=FALSE)
"speed"|"dist"
4|2
4|10
7|4
7|22
8|16
9|10
How can I create my own write.table function which creates an output like this (header with double pipes and data with preceding and succeeding pipes)?:
||"speed"||"dist"||
|4|2|
|4|10|
|7|4|
|7|22|
|8|16|
|9|10|
write.table can get you part of the way, but you will still need to do some fiddling around to get things to work just as you want.
Here's an example:
x <- capture.output(
write.table(head(cars), sep = "|", row.names = FALSE, eol = "|\n"))
x2 <- paste0("|", x)
x2[1] <- gsub("|", "||", x2[1], fixed=TRUE)
cat(x2, sep = "\n")
# ||"speed"||"dist"||
# |4|2|
# |4|10|
# |7|4|
# |7|22|
# |8|16|
# |9|10|
As a function, I guess in its most basic form it could look something like:
write.myOut <- function(inDF, outputFile) {
x <- capture.output(
write.table(inDF, sep = "|", row.names = FALSE, eol = "|\n"))
x <- paste0("|", x)
x[1] <- gsub("|", "||", x[1], fixed=TRUE)
cat(x, sep = "\n", file=outputFile)
}
I don't think that it is possible with write.table. Here is a workaround:
# function for formatting a row
rowFun <- function(x, sep = "|") {
paste0(sep, paste(x, collapse = sep), sep)
}
# create strings
rows <- apply(head(cars), 1, rowFun)
header <- rowFun(gsub("^|(.)$", "\\1\"", names(head(cars))), sep = "||")
# combine header and row strings
vec <- c(header, rows)
# write the vector
write(vec, sep = "\n", file = "myfile.sep")
The resulting file:
||"speed"||"dist"||
|4|2|
|4|10|
|7|4|
|7|22|
|8|16|
|9|10|

R Paste multiple

I am currently taking in multiple command line parameters within my R script such as :
args<-commandArgs(TRUE)
arg1 <- as.numeric(args[1])
arg2 <- as.numeric(args[2])
I am wanting to use these args within my paste string like below. My problem is that I can only figure out how to use 1 of the arguments and not both (arg1, arg2). Instead of "xxx" that I show below in my where clause (i.e. "columnname1 in (xxx)") how do I use the "arg1" command line parameter in place of "xxx"? I've tried a number of different ways and for some reason I can't figure it out. Should I concatenate two different strings to accomplish this or is there an easier way?
SQL<-paste(
"SELECT
*
FROM
table
WHERE
columnname1 in (xxx)
and
columnname2 in ('",arg2,"')",sep = "")
Thanks for your help!
Try:
SQL<-paste(
"SELECT
*
FROM
table
WHERE
columnname1 in ('",arg1,"')
and
columnname2 in ('",arg2,"')",sep = "", collapse="")
You could also use the following helper function that allows named substitutions:
SQL<-strsubst(
"SELECT * FROM table WHERE
columnname1 in ('$(arg1)') and
columnname2 in ('$(arg2)')",
list(arg1=arg1, arg2=arg2)
)
where strsubst is defined as follows:
strsubst <- function (template, map, verbose = getOption("verbose"))
{
pat <- "\\$\\([^\\)]+\\)"
res <- template
map <- unlist(map)
m <- gregexpr(pat, template)
idx <- which(sapply(m, function(x) x[[1]] != -1))
for (i in idx) {
line <- template[[i]]
if (verbose)
cat("input: |", template[[i]], "|\n")
starts <- m[[i]]
ml <- attr(m[[i]], "match.length")
sym <- substring(line, starts + 2, starts + ml - 2)
if (verbose)
cat("sym: |", sym, "|\n")
repl <- map[sym]
idx1 <- is.na(repl)
if (sum(idx1) > 0) {
warning("Don't know how to replace '", paste(sym[idx1],
collapse = "', '"), "'.")
repl[idx1] <- paste("$(", sym[idx1], ")", sep = "")
}
norepl <- substring(line, c(1, starts + ml), c(starts -
1, nchar(line)))
res[[i]] <- paste(norepl, c(repl, ""), sep = "", collapse = "")
if (verbose)
cat("output: |", res[[i]], "|\n")
}
return(res)
}

Resources