R: RScript Vector as argument - r

i am using the preinstalled package RScript in R.
I want to call the following R-Script with the name 'test.R' from the command prompt:
a <- c("a", "b", "c")
a
args <- commandArgs(TRUE)
b <- as.vector(args[1])
b
I use the following command:
RScript test.R c("d","e","f")
This creates following output:
[1] "a" "b" "c"
[1] "c(d,e,f)"
As you see, the first (and only) argument is interpreted as a String, then converted to a 1-dimensional vector. How can the argument be interpreted as a vector?
Sidenote: Of course the items of the vector could be separated into several arguments, but in my final project, there will be more than one vector-argument. And to implement something like this is my last resort:
RScript test.R "d" "e" "f" END_OF_VECTOR_1 "g" "h" "i" END_OF_VECTOR_2 "j" "k" "l"

You could use comma-separated lists.
On the command line:
RScript test.R a,b,c d,e,f g,h,i j
In your code:
vargs <- strsplit(args, ",")
vargs
# [[1]]
# [1] "a" "b" "c"
#
# [[2]]
# [1] "d" "e" "f"
#
# [[3]]
# [1] "g" "h" "i"
#
# [[4]]
# [1] "j"

You can clean up something like a = "c(1,2,3)" with:
as.numeric(unlist(strsplit(substr(a,3,nchar(a)-1), ",")))
which works fine as long as script will always be passed a properly formatted string, and you are aware of the expected format. In the RScript arguments, the c() part should not be listed, simply give it a quoted comma-separated list.

#flodel thanks for your answer, thats one way to do it. Beside that, I have found a workaround for my problem.
The following code in the file 'test.R' stores the arguments in 'args'. The text in 'args' is then evaluated to normal R expressions and as an output, a and b are given.
args <- commandArgs(TRUE)
eval(parse(text=args))
a
b
The code can be called in the command prompt as follows:
RScript test.R a=5 b=as.vector(c('foo', 'bar'))

Related

Why subtracting an empty vector in R deletes everything?

Could someone please enlighten me why subtracting an empty vector in R results in the whole content of a data frame being deleted? Just to give an example
WhichInstances2 <- which(JointProcedures3$JointID %in% KneeIDcount$Var1[KneeIDcount$Freq >1])
JointProcedures3 <-JointProcedures3[-WhichInstances2,]
Will give me all blanks in JointProcedures3 if WhichInstances2 has all its value as FALSE, but it should simply give me what JointProcedures3 was before those lines of code.
This is not the first time it has happened to me and I have asked my supervisor and it has happened to him as well and he just thinks t is a quirk of R.
Rewriting the code as
WhichInstances2 <- which(JointProcedures3$JointID %in% KneeIDcount$Var1[KneeIDcount$Freq >1])
if(length(WhichInstances2)>0)
{
JointProcedures3 <-JointProcedures3[-WhichInstances2,]
}
fixes the issue. But it should not have in principle made a scooby of a difference if that conditional was there or not, since if length(WhichInstances2) was equal to 0, I would simply be subtract nothing from the original JointProcedures3...
Thanks all for your input.
Let's try a simpler example to see what's happening.
x <- 1:5
y <- LETTERS[1:5]
which(x>4)
## [1] 5
y[which(x>4)]
## [1] "E"
So far so good ...
which(x>5)
## integer(0)
> y[which(x>5)]
## character(0)
This is also fine. Now what if we negate? The problem is that integer(0) is a zero-length vector, so -integer(0) is also a zero-length vector, so y[-which(x>5] is also a zero-length vector ..
What can you do about it? Don't use which(); instead use logical indexing directly, and use ! to negate the condition:
y[!(x>5)]
## [1] "A" "B" "C" "D" "E"
In your case:
JointID_OK <- (JointProcedures3$JointID %in% KneeIDcount$Var1[KneeIDcount$Freq >1])
JointProcedures3 <-JointProcedures3[!JointID_OK,]
For what it's worth, this is section 8.1.13 in the R Inferno, "negative nothing is something"
It seems you are checking for ids in a vector and you intend to remove them from another; probably setdiff is what you are looking for.
Consider if we have a vector of the lowercase letters of the alphabet (its an r builtin) and we want to remove any entry that matches something that is not in there ("ab") , as programmers we would wish for nothing to be removed and keep our 26 letters
# wont work
letters[ - which(letters=="ab")]
#works
setdiff(letters , which(letters=="ab"))
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u"
[22] "v" "w" "x" "y" "z"

Read multiple files into single list using pipes

I have a number simple files with a single entry per line and I want to read those files into a list with the content of a file as a vector.
> list(file_one = c(1,2,3,4), file_two = c(9,99,999))
$file_one
[1] 1 2 3 4
$file_two
[1] 9 99 999
...
This is basically the resulting format i want.
What I have so far is a similar result, but not correct:
> list.files("/home/x/y/z", pattern="^rep.*List$", full.names=TRUE) %>% lapply(read.table)
[[1]]
V1
1 a
2 b
3 c
4 d
How can I read the data in the correct format or transform it from here? - preferably I would have a "pipeline" to read the data:
list files
read files in correct format or
format the read data into a list of named vectors
Perhaps you need something like this
library(tidyverse)
list.files("xyz/", full.names = TRUE) %>%
set_names(basename(.)) %>%
map(read_lines)
#> $`rep1List`
#> [1] "a" "b" "c" "d" "e" "f"
#>
#> $rep2List
#> [1] "e" "f" "g" "h" "i" "j" "k"
#>
#> $rep3List
#> [1] "l" "m" "m" "o" "p" "q" "r" "s"
where each of the files look like this:
based on the information you gave, I would try something like below, using the purrr-Package:
list.files("/home/x/y/z", pattern="^rep.*List$", full.names = TRUE) %>%
purrr::map_df(., read.table, ADD YOUR ARGUMENTS HERE)
This is working for a real-life example for me. It fails with your made up file. I would have just commented, but I am too low. ^^

How to use a list as an argument in a function in R

myfunction<-function(x){if (x=="g"){g_var<-x g_nvar<-length(g_var)} return(g_nvar)}
I have written the above script to obtain specific elements out of a list. The argument x will be a list when I will call upon this function but R does not consider x as a list. How can I write a function such that when I provide a list, my output are the elements that I have specified in the function?
m
[[1]]
[[1]] [[1]]
[1] "g" "g" "h" "g" "g" "g" "k" "l"
[[2]]
[[2]] [[1]]
[1] "g" "h" "k" "k" "l" "g"
Expected result
[[1]] 5 # No. of g
[[2]] 2 # No. of g
Similarly I would like to obtain numbers for h,k and l also. I am putting m as x while calling the function.
For eg:- myfunction (m)
Your case is somewhat complicated by the fact that your m is not simply a list of character vectors, but, in your example, a list of 2 lists of 1 vector of characters, as would be generated by
m = list(strsplit("gghgggkl", ""), strsplit("ghkklg", ""))
If we want myfunction to operate on this data structure, we have to refer to the component of the length-1-lists with the operation [[1]] (see x[[1]] below), and, as loki suggested, we can use lapply to work on all components of the outer list, and sum with a logical expression to obtain the desired count:
myfunction = function(m) lapply(m, function(x) sum(x[[1]]=='g'))
myfunction(m)
result:
[[1]]
[1] 5
[[2]]
[1] 2

R: Check if strings in a vector are present in other vectors, and return name of the match

I need a tool more selective than %in% or match(). I need a code that matches a vector of string with another vector, and that returns the names of the matches.
Currently I have the following,
test <- c("country_A", "country_B", "country_C", "country_D", "country_E", "country_F") rating_3 <- c("country_B", "country_D", "country_G", "country_K")
rating_3 <- c("country_B", "country_D", "country_G", "country_K")
rating_4 <- c("country_C", "country_E", "country_M", "country_F)
i <- 1
while (i <= 33) {
print(i)
print(test[[i]])
if (grepl(test[[i]], rating_3) == TRUE) {
print(grepl(test[[i]], rating_3)) }
i <- i+1
},
This should check each element of test present in rating_3, but for some reason, it returns only the position, the name of the string, and a warning;
[1]
[country_A]
There were 6 warnings (use warnings() to see them)
I need to know what this piece of code fails, but I'd like to eventually have it return the name only when it's inside another vector, and if possible, testing it against several vectors at once, having it print the name of the vector in which it fits, something like
[1]
[String]
[rating_3]
How could I get something like that?
Without a reproducible example, it is hard to determine what exactly you need, but I think this could be done using %in%:
# create reprex
test <- sample(letters,10)
rating_3 <- sample(letters, 20)
print(rating_3[rating_3 %in% test])
[1] "r" "z" "l" "e" "m" "c" "p" "t" "f" "x" "n" "h" "b" "o" "s" "v" "k" "w" "a"
[20] "i"

Multiple gsub() expressions in R

I'm trying to clean a column of data from a data frame with many gsub commands.
Some examples would be:
df$col1<-gsub("-00070", "-0070", df$col1)
df$col1<-gsub("-00063", "-0063",df$col1)
df$col1<-gsub("F4", "FA", df$col1)
...
Looking at the column after running these lines of code, it looks like some of the changes have taken, but some have not. Moreover, if I run the block of code with the gsub() commands more changes start taking effect the more I run the block.
I'm very confused by this behavior, any information is appreciated.
There's probably a better way, but you could always use Map
new <- 1:3
old <- letters[1:3]
to.change <- letters[1:10]
Map(function(x, y) to.change <<- gsub(x, y, to.change), old, new)
to.change
# [1] "1" "2" "3" "d" "e" "f" "g" "h" "i" "j"

Resources