2017-10-19 9 views
1

mutate()を列名の一部に基づいて組み合わせて実行するより良い方法を見つけることを試みています。方法にはある名前FINAL_.dplyr - 列名の類似性に基づく式を変更

に与えられ(._A - ._B)/._C結果:

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) 

形を有する式:

たとえば、方法は、以下のコードでmutate機能を簡素化しますこれをmutate関数のコードの1行に単純化しますか?

+2

@bouncyballは変数を 'df'に変更しました – waealu

答えて

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 

注:

このアプローチはlapplyglueを使用していますgsubを使用して抽出されたプレフィックスから式を構築することもできます(または独自の接頭辞/接尾辞を付けることもできます)。 parse_quosureからrlangを使用して式を解析してquosureに変換します。その結果、expr_listquosureの名前付きリストです。!!!を使用して、引数を引用符で囲まずに別の式に接続することができます(mutate)。

最後の例のように、expression引数を調整することで、式を変更できます。

このメソッドの利点は、主に列名を操作して文字列(式)を作成するため、非常に高速です。欠点は、複数のパッケージを使用することです。

1

1つの考え方は、データフレームをロングフォーマットに変換して計算することです。

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 
関連する問題