簡體   English   中英

如何在 tidyverse 中將這個 function 與cross() 按列應用?

[英]How to apply this function columnwise with across() in tidyverse?

我需要在 tidyverse 中使用 function 基於現有列創建新列。 我計划使用across() ,因為它允許動態重命名新變量,這在我的情況下變得越來越重要,並且可以節省大量時間,特別是如果您的數據中有很多變量需要修改。 下面的 function 無法按預期按列應用,它的行為很奇怪,通過更改P參數的值,我每次都得到意想不到的 output,尤其是當我將一些值設置為 1 時,就好像應用了 ZC1C41252074 元素一樣但不是按列。

我想知道如何以更有效的方式編寫這段代碼來實現上述目標,我的意思是高效,更短,更快,更整潔。

代表

set.seed (123)
df <- tibble(id = 1:10,
               rosa = runif(10, min = 20.8, max = 36.5),
               lila = runif(10, min = 17, max = 37),
               blaue = runif(10, min = 23.3, max = 32.7))
df[c (2, 5, 8), c (2:4)] <- NA

代碼

myfun <- function(x, P = 2, na.rm = FALSE){
    P ^ (min (x, na.rm = na.rm) - x)
}

P <- c(2, 1.5, 1.1) # fiddle with numbers here and see the output each time changes 
names <- c ("rosa", "lila", "blaue")
df %>%
    select(!!names) %>%
    mutate(across(.cols = !!names,
                  .fns = ~myfun(.x, P, na.rm = TRUE),
                  .names = "{.col}_P"))

Output

   + # A tibble: 10 × 6
    rosa  lila blaue    rosa_P     lila_P  blaue_P
   <dbl> <dbl> <dbl>     <dbl>      <dbl>    <dbl>
 1  25.3  36.1  31.7  0.0718    0.0000526  0.00793
 2  NA    NA    NA   NA        NA         NA      
 3  27.2  30.6  29.3  0.581     0.439      0.643  
 4  34.7  28.5  32.6  0.000110  0.0108     0.00401
 5  NA    NA    NA   NA        NA         NA      
 6  21.5  35.0  30.0  1         0.288      0.605  
 7  29.1  21.9  28.4  0.00524   1          0.0753 
 8  NA    NA    NA   NA        NA         NA      
 9  29.5  23.6  26.0  0.469     0.856      0.881  
10  28.0  36.1  24.7  0.0114    0.0000543  1      
Warning messages:
1: Problem while computing `..1 = across(...)`.
ℹ longer object length is not a multiple of shorter object length 
2: Problem while computing `..1 = across(...)`.
ℹ longer object length is not a multiple of shorter object length 
3: Problem while computing `..1 = across(...)`.
ℹ longer object length is not a multiple of shorter object length 

預計 Output

df %>%
select(!!names) %>%
mutate(rosa_P =  2^(min (rosa, na.rm = TRUE) - rosa)) %>%
mutate(lila_P =  1.5^(min (lila, na.rm = TRUE) - lila)) %>%
mutate(blaue_P = 1.1^(min (blaue, na.rm = TRUE) - blaue))

   + # A tibble: 10 × 6
    rosa  lila blaue    rosa_P   lila_P blaue_P
   <dbl> <dbl> <dbl>     <dbl>    <dbl>   <dbl>
 1  25.3  36.1  31.7  0.0718    0.00314   0.514
 2  NA    NA    NA   NA        NA        NA    
 3  27.2  30.6  29.3  0.0192    0.0302    0.643
 4  34.7  28.5  32.6  0.000110  0.0708    0.468
 5  NA    NA    NA   NA        NA        NA    
 6  21.5  35.0  30.0  1         0.00498   0.605
 7  29.1  21.9  28.4  0.00524   1         0.701
 8  NA    NA    NA   NA        NA        NA    
 9  29.5  23.6  26.0  0.00407   0.515     0.881
10  28.0  36.1  24.7  0.0114    0.00320   1    

您的問題是P向量,因為它不會理解哪個數字屬於哪個呼叫,但會將across三個數字都傳遞給myfun 相反,您可以命名它並使用cur_column()

使用all_of / any_of而不是 , 並為名稱向量使用另一個names而不是names ,因為它也是基礎 function。 這可能會導致混亂。

library(dplyr)

P <- c(rosa = 2, lila = 1.5, blaue = 1.1)
colournames <- names(P) #c("rosa", "lila", "blaue")

df |>
  #select(all_of(colournames)) |>
  mutate(across(all_of(colournames),
                ~ P[cur_column()] ^ (min(., na.rm = TRUE) - .), # ~ my_fun(., P[cur_column()], na.rm = TRUE)
                .names = "{.col}_P"))

Output:

# A tibble: 10 × 6
    rosa  lila blaue    rosa_P   lila_P blaue_P
   <dbl> <dbl> <dbl>     <dbl>    <dbl>   <dbl>
 1  25.3  36.1  31.7  0.0718    0.00314   0.514
 2  NA    NA    NA   NA        NA        NA    
 3  27.2  30.6  29.3  0.0192    0.0302    0.643
 4  34.7  28.5  32.6  0.000110  0.0708    0.468
 5  NA    NA    NA   NA        NA        NA    
 6  21.5  35.0  30.0  1         0.00498   0.605
 7  29.1  21.9  28.4  0.00524   1         0.701
 8  NA    NA    NA   NA        NA        NA    
 9  29.5  23.6  26.0  0.00407   0.515     0.881
10  28.0  36.1  24.7  0.0114    0.00320   1    

更新,隨着 OP 示例的更改而更改。

暫無
暫無

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

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