r - how to use a variable in a variable - r

I have a data frame where the row names are words and I can call the first column of that row of data drame using something like
>df['rowB',1]
i know I can use paste to combine a variable and a string using paste to do something like
>paste("the value is ", df['rowB',1], "."]
and that will get me an output of the string with the value of the variable. what if rowname is a variable that equals 'rowB? I tried to do a first paste to put in the paste above, but the result of the first paste doesn't evaulate to the value, but rather is just a string that says
>rowname<-'rowB'
>type<-paste("relatype[\'", rowname, "\',1]", sep="")
'df['rowB',1]'
long story short, I want to input a value called 'rowname' as a parameter of a function and have it be evaluated for the value of rowname, so I can then put that value into a string within that same function.
I'm also open to a wholly different solution. any and all suggestions are welcome.
thanks

Not sure what the problem might be, not entirely clear from your description, but if rowname is a variable, you don't need anything special, because it will evaluate to it's value anyway. Let
mat <- matrix(1:10, nrow = 5)
rownames(mat) <- letters[1:5]
mat
## [,1] [,2]
##a 1 6
##b 2 7
##c 3 8
##d 4 9
##e 5 10
and rowname <- "b", then
rowname
##[1] "b"
so
mat[rowname, 1]
##b
##2
which is the same as mat["b", 1]. It only fails, if you use mat['rowname', 1].
If you want to put this in functions, you can do something like:
getElement <- function(mat, row.name, column.index) {
mat[row.name, column.index]
}
getElement(mat, "b", 1)
##b
##2
pasteSenstence <- function(mat, row.name, col.index) {
paste("The element of row", row.name, "and column", col.index, "is",
getElement(mat, row.name, col.index))
}
pasteSentence(mat, "b", 1)
##[1] "The element of row b and column 1 is 2"
which also works with rowname <- "b"
pasteSentence(mat, rowname, 1)
##[1] "The element of row b and column 1 is 2"

This should work:
paste("the value is ", get(df['rowname',1]), "."]
If you are not familiar, 'get' in r is similar to 'eval' in python.
x=c('a', 'c', 'b')
a=2
x[1]
'a'
get(x[1])
2

I'm afraid I don't understand the question; how is your function different from the following?
foo = function(rowname = "Species", d = t(iris)){
paste("I'm selecting", d[rowname, 1])
}
foo()
# [1] "I'm selecting setosa"

Related

How to assign the column name to the variable dynamically

I am currently developing an application and I need to loop through the columns of the data frame. For instance, if the data frame has the columns
char_set <- data.frame(character(),character(),character(),character(),stringsAsFactors = FALSE)
names(char_set) <- c("a","b","c","d")
If the input is given as "a", then the column name "b" should be assigned to the variable, say promote.
It throws an error Error in[.data.frame(char_set, i + 1) : undefined columns selected. Is there any solution?
char_name <- "a"
char_set <- data.frame(character(),character(),character(),character(),stringsAsFactors = FALSE)
names(char_set) <- c("a","b","c","d")
for (i in 1:ncol(char_set)) {
promote <- ifelse(names(char_set) == char_name,char_set[i+1], "-")
print(promote)
}
Thanks in advance!!!
This is actually quite interesting. I would suggest doing something on those lines:
char_name <- "a"
char_set <- data.frame(
a = 1:2,
b = 3:4,
c = 5:6,
d = 8:9,
stringsAsFactors = FALSE
)
res_dta <- data.frame(matrix(nrow = 2, ncol = 3))
for (i in wrapr::seqi(1, NCOL(char_set) - 1)) {
print(i)
if (names(char_set)[i] == char_name) {
res_dta[i] <- char_set[i + 1]
} else {
res_dta[i] <- char_set[i]
}
}
Results
char_set
a b c d
1 1 3 5 8
2 2 4 6 9
res_dta
X1 X2 X3
1 3 3 5
2 4 4 6
There are few generic points:
When you are looping through columns be mindful not fall outside data frame dimensions; running i + 1 on i = 4 will give you column 5 which will return an error for data frame with four columns. You may then decide to run to one column less or break for a specific i value
Not sure if I got your request right, for column names a you want to take values of column b; then column b stays as it was?
Broadly speaking, I'm of a view that this names(char_set)[i] == char_name requires more thought but you have a start with this answer. Updating your post with desired results would help to design a solution.
The problem in your code is that you are looping from 1 to the number of columns of the char_set df, then you are calling the variable char_set[i+1].
This, when the i index takes the maximum value, the instruction char_set[i+1] returns an error because there is no element with that index.
You can try with this solution:
char_name<-"a"
promote<-ifelse((which(names(char_set)==char_name)+1)<ncol(char_set),names(char_set)[which(names(char_set)==char_name)+1],"-")
promote
> [1] "b"
char_name<-"d"
promote<-ifelse((which(names(char_set)==char_name)+1)<ncol(char_set),names(char_set)[which(names(char_set)==char_name)+1],"-")
promote
> [1] "-"
However. when the variable char_name takes the value a, the variable promote will take the value that the set char_set has at the position after the element named a, which matches char_name.
I suggest you to think about the case in which the variable char_name takes the value d and you don't have any values in the char_set after d.

Assigning new vectors in a dataframe using cbind () and data.frame()

I am putting vectors into a dataframe using cbind() and data.frame(). And I want to add a new vector (price/money) when I build the dataframe.
flowers1 :
using data.frame() to create a dataframe ;
'=' to assign the new vector
flowers2 :
using cbind() to create a dataframe ;
'=' to assign the new vector
flowers3 :
using data.frame() to create a dataframe;
'<-' to assign the new vector
flowers4 :
using cbind() to create a dataframe;
'<-' to assign the new vector
flowers1 and 2 are what I expect but in flowers3, the header of the third column is odd. And in flowers4, the header of the third column is missing.
My questions are:
what caused this?
Is there any other difference between assigning vector using '<-' and '='
(I only know these two assign methods have different priority and different variable life time ?
Is it illegal or not recommended to assign a new vector when creating a dataframe?
Thanks!
name <- c('iris','daisy')
color <- c('purple','blue')
flowers1 <- data.frame(name,color,price = c(10,20))
flowers1
# output
name color price
1 iris purple 10
2 daisy blue 20
flowers2 <- cbind(name,color,price = c(10,20))
flowers2
# output
name color price
[1,] "iris" "purple" "10"
[2,] "daisy" "blue" "20"
flowers3 <- data.frame(name,color,price <- c(10,20))
flowers3
# output
name color price....c.10..20.
1 iris purple 10
2 daisy blue 20
flowers4 <- cbind(name,color,money <- c(10,20))
flowers4
# output
name color
[1,] "iris" "purple" "10"
[2,] "daisy" "blue" "20"
Use = to set function arguments, and <- as assignment operator. This could explain a little:
A = LETTERS[1:5]
B = letters[1:5]
d <- data.frame(A , B, CC <- seq(5, 1, -1))
d
CC # lives outside d!
d1 <- data.frame(A, B, DD = seq(5, 1, -1))
d1
DD # does not live outside d1

Reference vector from data frame using custom function

I'm trying to call a vector "a" from a data frame "df" using a function. I know I could do this just fine with the following:
> df$a
[1] 1 2 3
But I'd like to use a function where both the data frame and vector names are input separately as arguments. This is the best that I've come up with:
show_vector <- function(data.set, column) {
data.set$column
}
But here's how it goes when I try it out:
> show_vector(df, a)
NULL
How could I change this function in order to successfully reference vector df$a where the names of both are input to a function as arguments?
It's actually possible to do this without passing the column name as a string (in other words, you can pass in the unquoted column name:
show_vector <- function(data.set, column) {
eval(substitute(column), envir = data.set)
}
Usage example:
df <- data.frame(a = 1:3, b = 4:6)
show_vector(df, b)
# 4 5 6
I've wondered about this kind of thing a lot in the past and haven't found an easy fix. The best I've come up with is this:
df <- data.frame(c(1, 2, 3), c(4, 5, 6))
colnames(df) <- c("A", "B")
test <- function(dataframe, columnName) {
return(dataframe[, match(columnName, colnames(dataframe))])
}
test(df, "A")
Your code would work if you only put the column name in quotes i.e. show_vector(df, "a")
Other multiple ways to do this:
Using base functionality
func <- function(df, cname){
return(df[, grep(cname, colnames(df))])
}
Or even
func <- function(df, cname){
return(df[, cname])
}
You can use substitute to capture the input vector name as it is then use `as.character to make it as a character.
show_vector <- function(data.set, column) {
data.set[,as.character(substitute(column))]
}
Now lets take a look:
(dat=data.frame(a=1:3,b=4:6,c=10:12))
a b c
1 1 4 10
2 2 5 11
3 3 6 12
show_vector(dat,a)
[1] 1 2 3
show_vector(dat,"a")
[1] 1 2 3
It works.
we can also write a simple one where we just input a character string:
show_vector1 <- function(data.set, column) {
data.set[,column]
}
show_vector1(dat,"a")
[1] 1 2 3
Although this will not work if the column name is not a character:
show_vector1(dat,a)
**Show Traceback
Rerun with Debug
Error in `[.data.frame`(data.set, , column) : undefined columns selected**

How to assign a name to a specific element of a vector in R

My question is: How to assign a name to a specific element of a vector in R, particularly, using the assign(x, value) function.
Normally, to assign a value to a specific element of a vector, I would do as follows:
agent1[2] <- TRUE
But, this is not possible for me, because my (pre-assigned) variables are being called in a for-loop as follows:
for (i in 1:10) {
assign(paste("agent", i, "[2]", sep=""), TRUE)
}
Unfortunately, it seems that the assign function doesn't work for assigning values to specific elements in a vector! So while the following
for (i in 1:10) {
assign(paste("agent", i, "[2]", sep=""), TRUE)
}
does work to assign the TRUE value to agent1 to agent10, I cannot pick out that it assign the value to only the first (or nth) element in each of the agent vectors.
In a simple case, this can be seen in the following:
a <- 1:4
a[1] <- 2
a[1] == 2 # TRUE
However,
a <- 1:4
assign("a[1]", 2)
a[1] == 2 # FALSE
I'd appreciate any help on how to get around this. Thanks!
We can try
assign('a', `[<-`(a, 1, 2))
a[1]==2
#[1] TRUE
If we need to change the values for a range of index i.e. the 1st 3 values to 2
assign('a', `[<-`(a, 1:3, 2))
a
#[1] 2 2 2 4

concatenating strings to make variable name

I want to change the name of the output of my R function to reflect different strings that are inputted. Here is what I have tried:
kd = c("a","b","d","e","b")
test = function(kd){
return(list(assign(paste(kd,"burst",sep="_"),1:6)))
}
This is just a simple test function. I get the warning (which is just as bad an error for me):
Warning message:
In assign(paste(kd, "burst", sep = "_"), 1:6) :
only the first element is used as variable name
Ideally I would get ouput like a_burst = 1, b_burst = 2 and so on but am not getting close.
I would like split up a dataframe by contents of a vector and be able to name everything according to the name from that vector, similar to
How to split a data frame by rows, and then process the blocks?
but not quite. The naming is imperative.
Something like this, maybe?
kd = c("a","b","d","e","b")
test <- function(x){
l <- as.list(1:5)
names(l) <- paste(x,"burst",sep = "_")
l
}
test(kd)
You could use a vector instead of a list by way of setNames:
t1_6 <- setNames( 1:6, kd)
t1_6
a b d e b <NA>
1 2 3 4 5 6
> t1_6["a"]
a
1
Looking at the question again I wondered if you wnated to assign sequential names to a character vector:
> a1_5 <- setNames(kd, paste0("alpha", 1:5))
> a1_5
alpha1 alpha2 alpha3 alpha4 alpha5
"a" "b" "d" "e" "b"

Resources