[英]use dplyr mutate to create new columns based on a vector of column names
[英]dplyr - mutate formula based on similarities in column names
我試圖找到一種更好的方法,以基於列名的一部分在組合列上運行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
函數中的一行代碼?
一種想法是將數據幀轉換為長格式並進行計算。
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
這是另一種方法:
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
的rlang
將表達式解析為quosure
。 其結果是, expr_list
是命名列表quosure
的,然后我可以使用!!!
取消引用並將參數拼接為mutate
單獨表達式。
您可以通過調整expression
參數來更改公式,如上一個示例所示。
這種方法的優點是速度很快,因為我主要是操縱列名和創建字符串(表達式)。 缺點是它使用多個程序包。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.