R dplyr:使用字符串函数重命名变量

C8H*_*4O2 43 regex r rename dplyr

(有些相关的问题:在dplyr的重命名函数中输入新的列名作为字符串)

dplyrchain(%>%)的中间,我想用旧名称的函数替换多个列名(使用tolowergsub等)

library(tidyr); library(dplyr)
data(iris)
# This is what I want to do, but I'd like to use dplyr syntax
names(iris) <- tolower( gsub("\\.", "_", names(iris) ) )
glimpse(iris, 60)
# Observations: 150
# Variables:
#   $ sepal_length (dbl) 5.1, 4.9, 4.7, 4.6, 5.0, 5.4, 4.6,...
#   $ sepal_width  (dbl) 3.5, 3.0, 3.2, 3.1, 3.6, 3.9, 3.4,...
#   $ petal_length (dbl) 1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4,...
#   $ petal_width  (dbl) 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3,...
#   $ species      (fctr) setosa, setosa, setosa, setosa, s...

# the rest of the chain:
iris %>% gather(measurement, value, -species) %>%
  group_by(species,measurement) %>%
  summarise(avg_value = mean(value)) 
Run Code Online (Sandbox Code Playgroud)

我认为?rename把论点replace作为一个named character vector, with new names as values, and old names as names.

所以我尝试过:

iris %>% rename(replace=c(names(iris)=tolower( gsub("\\.", "_", names(iris) ) )  ))
Run Code Online (Sandbox Code Playgroud)

但是这个(a)返回Error: unexpected '=' in iris %>% ...,(b)需要通过名称引用链中先前操作的数据框,在我的实际用例中我不能这样做.

iris %>% 
  rename(replace=c(    )) %>% # ideally the fix would go here
  gather(measurement, value, -species) %>%
  group_by(species,measurement) %>%
  summarise(avg_value = mean(value)) # I realize I could mutate down here 
                                     #  instead, once the column names turn into values, 
                                     #  but that's not the point
# ---- Desired output looks like: -------
# Source: local data frame [12 x 3]
# Groups: species
# 
#       species  measurement avg_value
# 1      setosa sepal_length     5.006
# 2      setosa  sepal_width     3.428
# 3      setosa petal_length     1.462
# 4      setosa  petal_width     0.246
# 5  versicolor sepal_length     5.936
# 6  versicolor  sepal_width     2.770
# ... etc ....  
Run Code Online (Sandbox Code Playgroud)

Gui*_*the 43

这是一个非常晚的答案,2017年5月

dplyr 0.5.0.9004即将推出的0.6.0开始,许多新的重命名列方法(与maggritr管道操作符一致%>%)已添加到包中.

这些功能是:

  • rename_all
  • rename_if
  • rename_at

使用这些功能的方法有很多种,但与您的问题相关的方法stringr有以下几种:

df <- df %>%
  rename_all(
      funs(
        stringr::str_to_lower(.) %>%
        stringr::str_replace_all(., '\\.', '_')
      )
  )
Run Code Online (Sandbox Code Playgroud)

所以,继续使用管道:)(没有双关语意).

  • 好知道了,谢谢.另外值得注意的是,你可以将`df%<>%foo()`作为`df < - df%>%foo()的简写. (11认同)
  • 由于新的 dplyr 更新改变了 `funs()` 的工作方式(真希望他们没有这样做),您需要用 `list` 替换 `funs` 并在函数之前放置一个波浪号 ~,例如 `list(~str_replace) (., to_replace, 替换))` (2认同)

Mat*_*rde 36

我认为你正在查看文档plyr::rename,而不是dplyr::rename.你会做这样的事情dplyr::rename:

iris %>% rename_(.dots=setNames(names(.), tolower(gsub("\\.", "_", names(.)))))
Run Code Online (Sandbox Code Playgroud)

  • 您可以在后面的外观中使用`.`代替`iris`. (2认同)
  • 仅供参考:`rename_`*缓慢*被[弃用](https://github.com/hadley/dplyr/blob/b89a5ca40a038bc620c98638a4e12c353e5a4528/R/manip.r#L413).虽然@ Frank使用`setNames`似乎是最直接的(如果没有'dplyr`提供),我还没有找到明显的替代品. (2认同)

Fra*_*ank 23

这是一种绕过有点尴尬的rename语法的方法:

myris <- iris %>% setNames(tolower(gsub("\\.","_",names(.))))
Run Code Online (Sandbox Code Playgroud)

  • @Frank我用你的答案(+1)结束了,因为它是一种更简单的方式来做我想要的 - 并教我关于setNames--但@MatthewPlourde更真实地回答了所写的问题(即使用`rename`).谢谢你的时间! (2认同)

ali*_*ire 9

对于这个特殊[但相当普遍]的情况,该函数已经写在janitor包中:

library(janitor)

iris %>% clean_names()

##   sepal_length sepal_width petal_length petal_width species
## 1          5.1         3.5          1.4         0.2  setosa
## 2          4.9         3.0          1.4         0.2  setosa
## 3          4.7         3.2          1.3         0.2  setosa
## 4          4.6         3.1          1.5         0.2  setosa
## 5          5.0         3.6          1.4         0.2  setosa
## 6          5.4         3.9          1.7         0.4  setosa
## .          ...         ...          ...         ...     ...
Run Code Online (Sandbox Code Playgroud)

所以在一起,

iris %>% 
    clean_names() %>%
    gather(measurement, value, -species) %>%
    group_by(species,measurement) %>%
    summarise(avg_value = mean(value))

## Source: local data frame [12 x 3]
## Groups: species [?]
## 
##       species  measurement avg_value
##        <fctr>        <chr>     <dbl>
## 1      setosa petal_length     1.462
## 2      setosa  petal_width     0.246
## 3      setosa sepal_length     5.006
## 4      setosa  sepal_width     3.428
## 5  versicolor petal_length     4.260
## 6  versicolor  petal_width     1.326
## 7  versicolor sepal_length     5.936
## 8  versicolor  sepal_width     2.770
## 9   virginica petal_length     5.552
## 10  virginica  petal_width     2.026
## 11  virginica sepal_length     6.588
## 12  virginica  sepal_width     2.974
Run Code Online (Sandbox Code Playgroud)


mte*_*sha 7

我使用base,stringr和dplyr的雄辩尝试:

编辑:库(tidyverse)现在包括所有三个库.

library(tidyverse)
library(maggritr) # Though in tidyverse to use %>% pipe you need to call it 
# library(dplyr)
# library(stringr)
# library(maggritr)

names(iris) %<>% # pipes so that changes are apply the changes back
    tolower() %>%
    str_replace_all(".", "_")
Run Code Online (Sandbox Code Playgroud)

我这样做是为了用管道来构建功能.

my_read_fun <- function(x) {
    df <- read.csv(x) %>%
    names(df) %<>%
        tolower() %>%
        str_replace_all("_", ".")
    tempdf %<>%
        select(a, b, c, g)
}
Run Code Online (Sandbox Code Playgroud)


lok*_*oki 7

截至2020年rename_ifrename_atrename_all被标记取代。解决这个问题的最新方法 dplyr 方法是rename_with()

iris %>% rename_with(tolower)
Run Code Online (Sandbox Code Playgroud)

或更复杂的版本:

iris %>% 
  rename_with(stringr::str_replace, 
              pattern = "Length", replacement = "len", 
              matches("Length"))
Run Code Online (Sandbox Code Playgroud)

  • 刚刚发现:只需不给函数提供任何参数,而是将其指定为函数 `mydataframe %&gt;% rename_with(myawesomefunction)` (2认同)