通常,如果我试图重命名R中的数据帧的列,我会使用
data(iris)
colnames(iris)[colnames(iris) == "Petal.Length"] <- "petal_height"
所以我想如果我把它变成一个简单的函数,我会看到发生了什么
renamer <- function(data, oldname, newname) {
colnames(data)[colnames(data) == oldname] <- newname
}
但是,虽然该函数运行时没有错误,但似乎没有对数据帧进行任何明显的更改。
renamer(iris, "Petal.Length", "petal_height")
虽然这只是将newname
分配给虹膜的值
iris <- renamer(iris, "Petal.Length", "petal_height")
是否有人能够解释为什么这种行为正在发生?
请注意,我实际上并不需要重命名功能。我只是想了解为什么这不起作用,因为我认为它会。
平原:
renamer(iris, "Petal.Length", "petal_height")
不会更改iris
对象,因为R在函数内部使用局部范围。更改不会“泄漏”到调用上下文(没有做特殊的技巧。不要这样做)。
当你这样做时:
iris <- renamer(iris, "Petal.Length", "petal_height")
它不起作用,因为函数的返回值是return(...)
函数调用中的参数或函数的最后一个参数。所以:
renamer <- function(data, oldname, newname) {
colnames(data)[colnames(data) == oldname] <- newname
return(data)
}
应该与iris = renamer(iris,....)
合作
当您的功能完成时:
colnames(data)[colnames(data) == oldname] <- newname
R在该函数中做的最后一件事是评估newname
,所以它返回了"petal_height"
。
使用package::dplyr
iris %>% rename_all(function(x)tolower(gsub('\\.', '_', x, perl = TRUE))) %>% colnames()
[1] "sepal_length" "sepal_width" "petal_length" "petal_width" "species"
> data("iris")
> colnames(iris)
[1] "Sepal.Length" "Sepal.Width" "Petal.Length" "Petal.Width" "Species"
> iris %>% rename_all(function(x)sprintf('[OLD]%s | [NEW]%s', x, tolower(gsub('\\.', '_', x, perl = TRUE)))) %>%
head(1) %>% str
'data.frame': 1 obs. of 5 variables:
$ [OLD]Sepal.Length | [NEW]sepal_length: num 5.1
$ [OLD]Sepal.Width | [NEW]sepal_width : num 3.5
$ [OLD]Petal.Length | [NEW]petal_length: num 1.4
$ [OLD]Petal.Width | [NEW]petal_width : num 0.2
$ [OLD]Species | [NEW]species : Factor w/ 3 levels