This is my debut post here. So please bear with me if it doesn't live up to the high standards of clarity of more seasoned members.
I have 4 objects (representing 4 years) in my global environment that are lists consisting of 12 data-frames (one for each month in the year). They have a consistent structure, and the column names of the data-frames are all the same. I'm trying to change these column names of the data-frames in all 4 lists in one fell swoop using a function, and then overwrite all 4 objects in my global environment with new objects that have the data-frames with the new column names.
This is my function:
change.name <- function(data){
for (i in 1:length(data)){
names(data[[i]]) <- c("a", "b", "c", "d", "e")
}
assign(deparse(substitute(data)), value = data, envir = globalenv())
}
I use my function:
change.name(my_object1)
It works, except that I get this warning message:
Warning message: In assign(deparse(substitute(data)), value = data, envir = globalenv()) : only the first element is used as variable name
And the object in my global environment is not overwritten. I get a new object with a name like this:
"list(Jan = structure(list(a = c(11, 34, 36, 49, 55, 68, "
I understand that this has to do with the way the function variable is stored in the new environment R creates when running a function (or something along those lines).
My question is simple: How do I remedy this?
Right you are, the problem lies in the way function
s behave. Take a look at the following code, it might help
testFun1 <- function (val) {
a <<- val
assign("b",a)
}
testFun2 <- function (val) {
a <<- val
assign("b",a, pos = 1)
}
# environment pretty much empty apart from our functions
ls()
[1] "testFun1" "testFun2"
# run
set.seed(123)
testFun1(runif(1))
# less empty
ls()
[1] "a" "testFun1" "testFun2"
# still not quite it though
testFun2(runif(1))
# now that's better
ls()
[1] "a" "b" "testFun1" "testFun2"
For more information, take a look at the documentation ( ?assign
), especially the pos
argument.
You can fix this by using deparse(substitute(data))
before you do anything to data
:
# Let's change your function just a bit
change.name <- function(data){
# call deparse(substutite()) *before* you do anything to data
object_name <- deparse(substitute(data))
for (i in 1:length(data)){
names(data[[i]]) <- c("a", "b", "c", "d", "e")
}
assign(object_name, value = data, envir = globalenv())
}
# Create sample data
my_object1 <- lapply(1:12, function(x) {
data.frame(u = 1, v = 2, x = 3, y = 4, z = 5)
})
names(my_object1) <- month.name
change.name(my_object1)
ls()
#> [1] "change.name" "my_object1"
head(my_object1, 2)
#> $January
#> a b c d e
#> 1 1 2 3 4 5
#>
#> $February
#> a b c d e
#> 1 1 2 3 4 5
Created on 2018-12-20 by the reprex package (v0.2.1)
A more idiomatic (and probably safer) way to approach this task might be to simply use lapply
and setNames
:
my_object1 <- lapply(1:12, function(x) {
data.frame(u = 1, v = 2, x = 3, y = 4, z = 5)
})
names(my_object1) <- month.name
change.name <- function(obj){
lapply(obj,function(x) setNames(x,letters[1:5]))
}
my_object1 <- change.name(my_object1)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.