在管道R工作流中,将前缀或后缀添加到大多数数据框变量名

23

我希望在数据框的大多数变量名称中添加前缀或后缀,通常是在它们被某种方式转换之后,在执行连接之前。 我没有一种方法可以在不打破我的管道的情况下实现这一点。

例如,有了这些数据:

library(dplyr)
set.seed(1)
dat14 <- data.frame(ID = 1:10, speed = runif(10), power = rpois(10, 1),
                    force = rexp(10), class = rep(c("a", "b"),5))

我希望达到这个结果(注意变量名):

  class speed_mean_2014 power_mean_2014 force_mean_2014
1     a       0.5572500             0.8       0.5519802
2     b       0.2850798             0.6       1.0888116

我的当前方法是:

means14 <- dat14 %>%
  group_by(class) %>%
  select(-ID) %>%
  summarise_each(funs(mean(.)))  

names(means14)[2:length(names(means14))] <- paste0(names(means14)[2:length(names(means14))], "_mean_2014")

有没有替代那个笨重的最后一行,它会打断我的管道操作?我已经查看了 select()rename(),但不想显式地指定每个变量名,因为通常我想重命名除单个变量之外的所有变量,并且可能拥有比这个示例中更大的数据框。

我想象一个最终的管道命令,它近似于以下虚构函数:

appendname(cols = 2:n, str = "_mean_2014", placement = "suffix")

据我所知,这个东西并不存在。

6个回答

37
你可以将函数传递给rename_at,所以请这样做。
 means14 <- dat14 %>%
  group_by(class) %>%
  select(-ID) %>%
  summarise_all(funs(mean(.))) %>% 
  rename_at(vars(-class),function(x) paste0(x,"_2014"))

9
rename_at 函数也可以接受公式,因此你甚至可以省略匿名函数并执行重命名操作。rename_at(vars(-class), ~ paste0(., "_2014")) - ruaridhw
1
更简单的方法是,只需使用rename_at(vars(-class), paste0, "_2014")即可。 - Martin
3
从dplyr 1.0.0开始,您现在可以使用rename_with(~paste0(.,"_2014"), -class)中的rename_with函数。 - louish

7

在发布这个问题后,我进行了更多的实验,发现使用 setNames 函数并通过管道传递数据是可行的,因为它会返回一个 data.frame:

dat14 %>%
  group_by(class) %>%
  select(-ID) %>%
  summarise_each(funs(mean(.))) %>%
  setNames(c(names(.)[1], paste0(names(.)[-1],"_mean_2014"))) 

  class speed_mean_2014 power_mean_2014 force_mean_2014
1     a       0.5572500             0.8       0.5519802
2     b       0.2850798             0.6       1.0888116

这样做的好处是,如果原始数据框中存在重复的名称(而在具有重复名称的tibble上使用rename将失败),它可以帮助解决问题。 - Arthur Yip

6
这个稍微快一些,但并不完全符合您的要求:
dat14 %>%
  group_by(class) %>%
  select(-ID) %>%
  summarise_each(funs(mean(.))) -> means14 

names(means14)[-1] %<>% paste0("_mean_2014")

如果您以前没有使用过%< >%运算符,一定要查看此链接,它是一个非常有用的工具。
您还可以使用它来重新计算或舍入某些列,例如df$meancolumn %< >% round()等等,这种情况经常出现,只需要少量编写即可。

很好的使用了 %<>%,感谢您发布链接,再次阅读作为复习总是很好的。 - infominer
1
谢谢,我完全爱上了%<>%运算符,它非常有用,因为那些任务经常出现,你还可以用它来重新计算或舍入一些列,就像这样:df$meancolumn %<>% round()等等,它经常用到并且帮你省去了很多写代码的时间。 - grrgrrbla
肯定是一种改进,谢谢。我经常使用%<>%来替换df <- df %>% ...,但从未想过将其用于其他数据类型,如向量。你的round()示例非常简洁! - Sam Firke
谢谢。由于这是有用的信息,我将示例添加到我的答案中。很高兴你自己解决了问题。这总是最好的方式 :) - grrgrrbla

4

从2017年2月起,您可以使用dplyr命令rename_(...)来完成此操作。

对于这个例子,您可以这样做。

dat14 %>%
  group_by(class) %>%
  select(-ID) %>%
  summarise_each(funs(mean(.))) %>%
  rename_(names(.)[-1], paste0(names(.)[-1],"_mean_2014"))) 

这与使用 set_names 的答案非常相似,但也适用于 tibbles!


0

这更像是一种退步,但您可以考虑重新塑造数据以便同时将函数应用于多年。这将保持整洁性。如果您最终要比较不同的年份,将年份作为数据框中的单独变量而不是存储在名称中可能是有意义的。您应该能够使用summarise_来获得mean_year行为。请参见http://cran.r-project.org/web/packages/dplyr/vignettes/nse.html

library(dplyr)
library(tidyr)
set.seed(1)
dat14 <- data.frame(ID = 1:10, speed = runif(10), power = rpois(10, 1),
                    force = rexp(10), class = rep(c("a", "b"),5))

dat14 %>% 
  gather(variable, value, -ID, -class) %>% 
  mutate(year = 2014) %>% 
  group_by(class, year, variable)%>% 
  summarise(mean = mean(value))`

0

虽然Sam Firkes使用setNames()的解决方案肯定是保持完整管道的唯一解决方案,但它无法与dplyrtbl对象一起使用,因为通常的基本R命名函数的方法无法访问列名。这里是一个函数,您可以在具有tbl对象的管道中使用,感谢hrbrmstr的this解决方案。它在指定的列索引处添加预定义的前缀和后缀。默认情况下是所有列。

tbl.renamer <- function(tbl,prefix="x",suffix=NULL,index=seq_along(tbl_vars(tbl))){
  newnames <- tbl_vars(tbl) # Get old variable names
  names(newnames) <- newnames
  names(newnames)[index] <- paste0(prefix,".",newnames,suffix)[index] # create a named vector for .dots
  rename_(tbl,.dots=newnames) # rename the variables
}

示例用法(假设auth_users是一个tbl_sql对象):

auth_user %>% tbl_vars
tbl.renamer(auth_user) %>% tbl_vars
auth_user %>% tbl.renamer %>% tbl_vars
auth_user %>% tbl.renamer(index = c(1,5)) %>% tbl_vars

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接