在管道 R 工作流中为大多数 data.frame 变量名称添加前缀或后缀
Posted
技术标签:
【中文标题】在管道 R 工作流中为大多数 data.frame 变量名称添加前缀或后缀【英文标题】:Adding prefix or suffix to most data.frame variable names in piped R workflow 【发布时间】:2015-07-09 01:01:15 【问题描述】:我想为 data.frame 中的大多数变量名称添加后缀或前缀,通常是在它们都以某种方式进行转换之后和执行连接之前。我没有办法在不破坏管道的情况下做到这一点。
例如,使用以下数据:
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()
,但不想明确指定每个变量名称,因为我通常想重命名所有 except 单个变量并且可能有更广泛的数据。框架比在这个例子中。
我正在想象一个最终的管道命令,它近似于这个虚构的功能:
appendname(cols = 2:n, str = "_mean_2014", placement = "suffix")
据我所知不存在。
【问题讨论】:
【参考方案1】:您可以将函数传递给 rename_at,这样做
means14 <- dat14 %>%
group_by(class) %>%
select(-ID) %>%
summarise_all(funs(mean(.))) %>%
rename_at(vars(-class),function(x) paste0(x,"_2014"))
【讨论】:
rename_at
也接受公式,因此您甚至可以取消匿名函数 rename_at(vars(-class), ~ paste0(., "_2014"))
更简单,也可以rename_at(vars(-class), paste0, "_2014")
从 dplyr 1.0.0 开始,您现在可以使用 rename_with
,rename_with(~paste0(.,"_2014"), -class)
【参考方案2】:
在发布此问题后进行了额外的实验后,我发现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
【讨论】:
这样做的好处是,如果原始数据框中有重复名称,它可以帮助解决问题(而在重复名称的小标题上使用重命名会失败)【参考方案3】:这有点快,但不完全是你想要的:
dat14 %>%
group_by(class) %>%
select(-ID) %>%
summarise_each(funs(mean(.))) -> means14
names(means14)[-1] %<>% paste0("_mean_2014")
如果你之前没有使用过 %%-operator,一定要检查一下这个link,它是一个超级有用的工具。
你也可以用它来重新计算或舍入一些列,比如df$meancolumn %<>% round()
,等等,它只是经常出现,只是为你节省了很多写作
【讨论】:
很好地使用了%<>%
,感谢您发布链接,作为复习再次阅读总是很好
谢谢,我完全爱上了%<>%
运算符,它非常有用,因为这些任务经常出现,你也可以用它来重新计算或舍入一些列,像这样@ 987654326@,等等,它只是经常出现,只是为你节省了很多写作
绝对是一个改进,谢谢。我经常使用%<>%
来替换df <- df %>% ...
,但我从未想过将它用于其他数据类型,如向量。您使用round()
的示例非常简洁!
谢谢。鉴于它是有用的信息,我将示例添加到我的答案中。很高兴你自己解决了你的问题。这总是最好的方式:)【参考方案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
的答案非常相似,但也适用于小标题!
【讨论】:
【参考方案5】:这更像是退后一步,但您可能会考虑重塑数据,以便将函数同时应用于多年。这将保持整洁。如果您最终想要比较不同的年份,将年份作为数据框中的单独变量而不是将年份存储在名称中可能是有意义的。您应该能够使用 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))`
【讨论】:
【参考方案6】:虽然使用 setNames()
的 Sam Firkes 解决方案肯定是保持管道完整的唯一解决方案,但它不适用于来自 dplyr
的 tbl
对象,因为列名无法通过通常的基础 R 中的方法访问命名功能。由于 hrbrmstr 的 this 解决方案,这是一个您也可以在带有 tbl
对象的管道中使用的函数。它在指定的列索引处添加预定义的前缀和后缀。默认为所有列。
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
【讨论】:
以上是关于在管道 R 工作流中为大多数 data.frame 变量名称添加前缀或后缀的主要内容,如果未能解决你的问题,请参考以下文章