我正在尝试找到一种更好的方法,根据列名的一部分对列组合运行mutate()
。
例如,在以下代码中简化mutate
函数的方法:
df <- data.frame(LIMITED_A = c(100,200),
UNLIMITED_A = c(25000,50000),
LIMITED_B = c(300,300),
UNLIMITED_B = c(500,500),
LIMITED_C = c(2,10),
UNLIMITED_C = c(5,20))
df %>%
mutate(FINAL_LIMITED = (LIMITED_A - LIMITED_B) / LIMITED_C,
FINAL_UNLIMITED = (UNLIMITED_A - UNLIMITED_B) / UNLIMITED_C)
形式为(._A - ._B) / ._C
的公式,结果名称为FINAL_.
有没有办法将此简化为mutate
函数中的单行代码?
答案 0 :(得分:2)
一个想法是将数据帧转换为长格式并进行计算。
library(dplyr)
library(tidyr)
df2 <- df %>%
mutate(ID = 1:n()) %>%
gather(Type, Value, -ID) %>%
separate(Type, into = c("Type", "Group")) %>%
spread(Group, Value) %>%
mutate(Final = (A - B)/C)
df2
ID Type A B C Final
1 1 LIMITED 100 300 2 -100
2 1 UNLIMITED 25000 500 5 4900
3 2 LIMITED 200 300 10 -10
4 2 UNLIMITED 50000 500 20 2475
您始终可以将数据帧转换回宽屏格式。
df3 <- df2 %>%
gather(Group, Value, A:Final) %>%
unite(Col, Type, Group) %>%
spread(Col, Value) %>%
select(colnames(df),
FINAL_LIMITED = LIMITED_Final,
FINAL_UNLIMITED = UNLIMITED_Final)
LIMITED_A UNLIMITED_A LIMITED_B UNLIMITED_B LIMITED_C UNLIMITED_C FINAL_LIMITED FINAL_UNLIMITED
1 100 25000 300 500 2 5 -100 4900
2 200 50000 300 500 10 20 -10 2475
答案 1 :(得分:2)
这是一种不同的方法:
library(dplyr)
library(rlang)
library(glue)
dynamic_mutate = function(DF,
col_names = gsub("(.*)_\\w+$", "\\1", names(DF)),
expression = "({x}_A - {x}_B)/{x}_C",
prefix = "FINAL"){
name_list = col_names %>%
unique() %>%
as.list()
expr_list = name_list %>%
lapply(function(x) parse_quosure(glue(expression))) %>%
setNames(paste(prefix, name_list, sep = "_"))
DF %>% mutate(!!!expr_list)
}
<强>结果:强>
> df %>%
+ dynamic_mutate()
LIMITED_A UNLIMITED_A LIMITED_B UNLIMITED_B LIMITED_C UNLIMITED_C FINAL_LIMITED
1 100 25000 300 500 2 5 -100
2 200 50000 300 500 10 20 -10
FINAL_UNLIMITED
1 4900
2 2475
> df %>%
+ dynamic_mutate(c("LIMITED", "UNLIMITED"), prefix = "NEW")
LIMITED_A UNLIMITED_A LIMITED_B UNLIMITED_B LIMITED_C UNLIMITED_C NEW_LIMITED
1 100 25000 300 500 2 5 -100
2 200 50000 300 500 10 20 -10
NEW_UNLIMITED
1 4900
2 2475
> df %>%
+ dynamic_mutate(c("UNLIMITED"), prefix = "NEW")
LIMITED_A UNLIMITED_A LIMITED_B UNLIMITED_B LIMITED_C UNLIMITED_C NEW_UNLIMITED
1 100 25000 300 500 2 5 4900
2 200 50000 300 500 10 20 2475
> df %>%
+ dynamic_mutate(c("A", "B", "C"), "LIMITED_{x} + UNLIMITED_{x}")
LIMITED_A UNLIMITED_A LIMITED_B UNLIMITED_B LIMITED_C UNLIMITED_C FINAL_A FINAL_B FINAL_C
1 100 25000 300 500 2 5 25100 800 7
2 200 50000 300 500 10 20 50200 800 30
备注:强>
此方法使用lapply
和glue
从使用gsub
提取的前缀构造表达式(或者您可以提供自己的前缀/后缀)。然后使用来自parse_quosure
的{{1}}将表达式解析为rlang
。因此,quosure
是expr_list
的命名列表,然后我可以使用quosure
取消引用并将参数拼接到!!!
中的单独表达式中。
您可以通过调整mutate
参数来更改公式,如上一个示例所示。
这种方法的优点是它非常快,因为我主要是操纵列名和创建字符串(表达式)。缺点是它使用多个包。