R NameValue from CSV String - access value via name - r

I am new to R and have a question not knowing how to solve it. Maybe you can help?
I do have a separated name/value input string: param1=test;param2=3;param3=140;
I would like to access a value via it's name in R.
Something like using
myParams["param1]
I already tried something like:
input = "param1=test;param2=3;param3=140;"
output1 = strsplit(input,";")[[1]]
output2 = do.call(rbind, strsplit(output1, "="))
to get a matrix but am missing the rest..

You could define a custom function myParams:
# Your sample data
input = "param1=test;param2=3;param3=140;"
output1 = strsplit(input,";")[[1]]
output2 = do.call(rbind, strsplit(output1, "="))
# Define function
myParams <- function(par, df = output2) {
return(df[which(df[, 1] == par), 2])
}
myParams("param1");
#[1] "test"
myParams("param2");
#[1] "3"

A simple way would be to create a dataframe out of that matrix first and then access the value via row names
input = "param1=test;param2=3;param3=140;"
output1 = strsplit(input,";")[[1]]
output2 = do.call(rbind, strsplit(output1, "="))
temp = data.frame(output2,row.names = TRUE)
# X2
#param1 test
#param2 3
#param3 140
temp[,"param1"]
#test
temp[,"param2"]
#3
temp[,"param3"]
#140

Related

Using paste and sum inside a for-loop

I need to compare a character string to multiple others and tried to do it the following way:
empty = character(0)
ps_2 = c("h2","h3")
ps_3 = c("h3", "h4")
visible = ("h2")
i = 2
ps_t = empty
ps_t <- append(ps_t, sum(visible %in% paste("ps_", i, sep="")))
With the intention to write a loop instead of i = 2, in order to cycle trough ps_2,ps_3,...
However I think it's not working since the paste() command returns a string instead of the character string with the name: ps_2.
How can I fix this?
Thanks for the time and effort!
Kind regards,
A fellow datafanatic!
The function you need is get(), which gets the value of the object.
ps_t <- ps_t = NULL
sapply(2:3, function(i) append(ps_t, sum(visible %in% get(paste0("ps_", i)))))
Or simply:
sapply(2:3, function(i) sum(visible %in% get(paste0("ps_", i))))
Output
[1] 1 0
You can use eval in R to convert the string to a variable name. You can find the solution here.
Here's what your code will look like:
ps_t <- c(0, (sum(visible %in% eval(parse(text = paste("ps_", i, sep=""))))))
It will give you a numeric vector.
OR
You can use get.
ps_t <- append(0, sum(visible %in% get(paste("ps_", i, sep = ""))))
ps_t

R adding values to vector in for loop

I'm working in R & using a for loop to iterate through my data:
pos = c(1256:1301,6542:6598)
sd_all = null
for (i in pos){
nameA = paste("A", i, sep = "_")
nameC = paste("C", i, sep = "_")
resA = assign(nameA, unlist(lapply(files, function(x) x$percentageA[x$position==i])))
resC = assign(nameC, unlist(lapply(files, function(x) x$percentageC[x$position==i])))
sd_A = sd(resA)
sd_C = sd(resC)
sd_all = ?
}
now I want to generate a vector called 'sd_all' that contains the standard deviations of resA & resC. I cannot just do 'sd_all = c(sd(resA), sd(resC))', because then I only use one value in 'pos'. I want to do it for all values in 'pos' off course.
It looks like you'd be best served with sd_all as a list object. That way you can insert each of your 2 values ( sd(resA) and sd(resC) ).
Initialising a list is simple (this would replace the second line of your code):
sd_all <- list()
Then you can insert both the values you want to into a single list element like so (this would replace the last line in your for loop):
sd_all[[ i ]] <- c( sd( resA ), sd( resC ) )
After your loop, you can then insert this list as a column in a data.frame if that's what you'd like to do.

Evaluate dataframe$column expression stored as a string value

Can a string of the form below be evaluated so that it is equivalent to the same "literal" expression?
Example data and code:
df.name = data.frame(col1 = 1:5, col2 = LETTERS[seq(1:5)], col3 = letters[seq(1:5)], stringsAsFactors = FALSE)
col.name = "col2"
row.num = "4"
var1 = str_c("df.name$", col.name,"[",row.num,"]")
> var1
[1] "df.name$col2[4]"
The literal works as expected
> df.name$col2[4]
[1] D
get() is not equivalent:
get(var1)
## Error in get(var1) : object 'df.name$col2[4]' not found
This form of get() "works" but does not solve the problem
get("df.name")$col2[4]
[1] D
Per other posts I've tried eval(parse()) and eval(parse(text())) without success.
I'm trying to create a function that will search (subset) df.name using the col.name passed to the function. I want to avoid writing a separate function for each column name, though that will work since I can code df.name$col2[row.num] as a "literal".
EDIT
The example code should have shown the row.num as type numeric / integer, i.e., row.num = 4
You are almost there:
> eval(parse(text = var1))
[1] "D"
Because parse expecting file by default, you need to specify the text parameter.
I'm trying to create a function that will search (subset) df.name using the col.name passed to the function.
Set up data:
df.name = data.frame(col1 = 1:5, col2 = LETTERS[1:5], ## seq() is unnecessary
col3 = letters[1:5],
stringsAsFactors = FALSE)
col.name = "col2"
row.num = "4"
Solving your ultimate (index the data frame by column name) rather than your proximal (figure out how to use get()/eval() etc.) question: as #RichardScriven points out,
f <- function(col.name,row.num,data=df.name)
return(data[[col.name]][as.numeric(row.num)])
}
should work. It would probably be more idiomatic if you specified the row number as numeric rather than character, if possible ...

Executing a function with paste to create a new variable in a dataframe in R

Data:
structure(list(`p value` = c(0.00151124736422317, 0.804709799937324,
0.0192537412780042, 0.000467854188597731, 4.80216666553605e-06,
0.0231434946595433), significance = c(TRUE, FALSE, TRUE, TRUE,
TRUE, TRUE)), .Names = c("p value", "significance"), row.names = c("Q5.i",
"Q5.ii", "Q5.iii", "Q5.iv", "Q5.v", "Q5.vi"), class = "data.frame")
Objective:
To create a function that would take input of dataframe name and a (new) variabe name.
The function would:
create a new variable that is based on the row name of the dataframe
delete the row name
reorder the variable so that the newly created
column is first column
Challenges:
I am stuck at the first step.
I've searched the internet and stackoverflow for snippets of code that would help and I've managed to hammer something although it couldn't work.
What have I tried:
row2col<-function(df, varname){
eval(parse(text=paste(df, "[[", "'", varname, "'", "]]", "<-row.names(", df, ")", sep="")))
}
row2col<-function(df, varname){
assign(parse(text=paste(df, varname, sep="$")), row.names(df))
}
Results:
nothing happened (not even an error message)
a character vector of row names (rather than a variable within the dataframe) was created
Thanks for your help and attention to this post.
You don't need to use eval, parse, assign - that's in many cases not the right approach. Here's a simple alternative:
row2col <- function(dat, varname) {
dat[[varname]] <- row.names(dat)
row.names(dat) <- NULL
dat[, c(varname, setdiff(names(dat), varname))]
}
And then you can test it:
> row2col(df, "testcol")
# testcol p value significance
#1 Q5.i 1.511247e-03 TRUE
#2 Q5.ii 8.047098e-01 FALSE
#3 Q5.iii 1.925374e-02 TRUE
#4 Q5.iv 4.678542e-04 TRUE
#5 Q5.v 4.802167e-06 TRUE
#6 Q5.vi 2.314349e-02 TRUE
Create new var using row names.
data$new_var <- row.names(data)
Reset row names
row.names(data) <- NULL
Reorder data frame with new var first
data <- data[, c(ncol(data):(ncol(data) - 1))]

zoo create new column with dynamic column name

I am trying to add a column to a zoo object. I found merge which works well
test = zoo(data.frame('x' = c(1,2,3)))
test = merge(test, 'x1' = 0)
However when I try to name the column dynamically, it no longer works
test = merge(test, paste0('x',1) = 0)
Error: unexpected '=' in "merge(test,paste0('x',1) ="
I have been working with data frames and the same syntax works
test = data.frame('x' = c(1,2,3))
test[paste0('x',1)] = 0
Can someone help explain what the problem is and how to get around this?
Try setNames :
setNames( merge(test, 0), c(names(test), paste0("x", 1)) )
or names<-.zoo like this:
test2 <- merge(test, 0)
names(test2) <- c(names(test), paste0("x", 1))
I found this solution very easy and elegant. It uses the eval() function to interpret a string as an R command. Thus, you are completely free to assemble the string exactly the way you want:
test = merge(test, paste0("x",1) = 0)
# does not work (see question)
test[,"x1"] <- 0
# does not work for uninitialized columns
test$x1 <- 0
# works to initialize a new column
# so lets trick R by assembling this command out of strings:
newcolumn <- "x1"
eval(parse(text=paste0("test$",newcolumn," <- 0")))
# welcome test$x1 :-)
Merge expects a string as variable name, it doesn't understand variable names that are return values of functions. Why not
test = zoo(data.frame('x' = c(1,2,3)))
var <- paste0('x',1)
test = merge(test, var = 0)

Resources