簡體   English   中英

如何將列名傳遞給涉及變異的 function?

[英]How do I pass a column name to a function involving mutate?

我正在嘗試編寫一個 function ,它接受一個字符串並將其用作等號兩側的dplyr::mutate()中的列名。 這是我想要自動化的示例:

cars %>% 
  mutate(
    new_speed = speed + 5,
    revised_speed = case_when(new.speed < 12 ~ 0,
                              new.speed == 12 ~ 1,
                              new.speed > 12 ~ 1/new_speed), 
  )

為了對任何數據集自動執行此過程,我需要 1) 將前綴“new”附加到我指定的任何列名,以及 2) 創建一個附加列,其前綴為“improved”,這取決於第一列的值。

function 應該如下所示,其中 ** ** 替換為正確的語法:

insert_names <- function(df, oldname, prefix_1, prefix_2){
  df %>% mutate(
    **prefix_1.oldname** = oldname + 5,
    **prefix_2.oldname** = case_when(**prefix_1.oldname** < 12 ~ 0,
                                     **prefix_1.oldname** == 12 ~ 1,
                                     **prefix_1.oldname** > 12 ~ 1/**prefix_1.oldname**),
    
  )
}

正確的 function 應該像這樣重現原始 output:

insert_names(cars, oldname = "speed", prefix_1 = "new", prefix_2 = "improved")

雖然如果這更容易,我可以不引用speed

  • 我們可以用
library(dplyr)
library(data.table)

insert_names <- function(df, oldname, prefix_1, prefix_2){
    pre1_old <- paste0(prefix_1 , "." , oldname)
    pre2_old <- paste0(prefix_2 , "." , oldname)
    d <- df %>% mutate(
        x = !!sym(oldname) + 5,
        y = case_when(x < 12 ~ 0,
                      x == 12 ~ 1,
                      x > 12 ~ 1/x),
        
    )
    d  %>% setnames(c("x" , "y") ,c(pre1_old ,pre2_old))
    d
}

insert_names(cars, oldname = "speed", prefix_1 = "new", prefix_2 = "improved")
  • 輸出
  speed dist new.speed improved.speed
1      4    2         9     0.00000000
2      4   10         9     0.00000000
3      7    4        12     1.00000000
4      7   22        12     1.00000000
5      8   16        13     0.07692308
6      9   10        14     0.07142857
7     10   18        15     0.06666667
8     10   26        15     0.06666667
9     10   34        15     0.06666667
10    11   17        16     0.06250000
11    11   28        16     0.06250000
12    12   14        17     0.05882353
13    12   20        17     0.05882353
14    12   24        17     0.05882353
15    12   28        17     0.05882353

使用rlang的一個很好的例子:

library(dplyr)
library(rlang)

insert_names <- function(df, oldname, prefix_1, prefix_2){
  
  new_name_1 <- paste(prefix_1, oldname, sep = ".")
  new_name_2 <- paste(prefix_2, oldname, sep = ".")
  
  df %>% mutate(
    !!new_name_1 := !!sym(oldname) + 5,
    !!new_name_2 := case_when(!!sym(new_name_1) < 12 ~ 0,
                                     !!sym(new_name_1) == 12 ~ 1,
                                     !!sym(new_name_1) > 12 ~ 1/!!sym(new_name_1)),
  )
}

insert_names(cars, "speed", "new", "newer")
#>    speed dist new.speed newer.speed
#> 1      4    2         9  0.00000000
#> 2      4   10         9  0.00000000
#> 3      7    4        12  1.00000000
#> 4      7   22        12  1.00000000
#> 5      8   16        13  0.07692308
#> 6      9   10        14  0.07142857
#> 7     10   18        15  0.06666667
#> 8     10   26        15  0.06666667
#> 9     10   34        15  0.06666667
#> 10    11   17        16  0.06250000
...

編輯

我確實看到大約在同一時間發布的另一個答案使用了相同的方法。 細微的區別在於新列的命名位置,無論是在創建時還是在返回數據框之前。

為此,您需要使用強制和化解運算符。 雙花括號強制和解散給定的字符串,它允許您 (1) 將列名作為字符串引用和 (2) 強制 function 參數。 使用這些運算符時,您必須使用“:=”作為賦值運算符。 我還使用 get() 從引用的字符串名稱中獲取列值。 不確定這是否是最有效的方法,我相信有人可能有更好的代碼,但它確實有效。

(注意:, 或“bang-bang”是一個強制運算符,equo() 化解,{{}} 兩者兼而有之,相當於 !!enquo() - 不確定每個地方是否需要 {{}}我把它們放在這段代碼中但是是的)

這是一個工作代碼:

insert_names <- function(df, oldname, prefix_1, prefix_2){
  col_name1 = paste0(prefix_1, "_", oldname)
  col_name2 = paste0(prefix_2, "_", oldname)
  df %>% mutate(
    {{col_name1}} := get(!!oldname) + 5,
    {{col_name2}} := case_when(get(!!col_name1) < 12 ~ 0,
                               get(!!col_name1) == 12 ~ 1,
                               TRUE ~ 1/get(!!col_name1)
    
  ))
}

insert_names(cars, oldname = "speed", prefix_1 = "new", prefix_2 = "improved")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM