簡體   English   中英

lapply()在數據框的多個列上使用函數

[英]lapply() to use a function over multiple columns of a dataframe

我正在跟蹤一段時間內個體的體重,下面的函數使我可以計算相對於初始值(本質上是特定天的體重除以體重)得出的某天某人的體重百分比。在第1天觀察到)。

variability <- function(df, column_number) {
  variable_name <- paste0("var_BW", column_number)

   df %>% 
  mutate(!!variable_name := round(100*(df[,column_number]/df[1,column_number]), 1))

}

如果我在一列上使用此函數,則該函數運行良好,但是由於我有很多人,因此我想使用apply()系列在一個數據幀的多個列上使用該函數(例如,在一個數據幀的列1:8上)下面的數據框):

 BW1  BW2  BW3  BW4  BW5  BW6  BW7  BW8
1 18.4 19.6 20.7 17.4 18.7 18.9 19.0 17.8
2 18.1 19.3 20.0 17.5 18.3 19.4 19.5 18.0
3 17.7 18.9 20.4 17.3 18.3 19.2 19.3 17.9

我最初的猜測是將列號存儲在列表中,然后將該列表作為參數傳遞給lapply()函數,例如:

l <- list(1:8)
lapply(working_df, variability, l)

但是,當我這樣做時,出現以下錯誤:

Error in UseMethod("mutate_") : 
  no applicable method for 'mutate_' applied to an object of class "c('double', 'numeric')" 

有什么想法嗎?

這樣合適嗎
由於可以對相對百分比部分進行矢量化處理,因此我們可以大大簡化事情。

bw <- read.table(text="
 BW1  BW2  BW3  BW4  BW5  BW6  BW7  BW8
1 18.4 19.6 20.7 17.4 18.7 18.9 19.0 17.8
2 18.1 19.3 20.0 17.5 18.3 19.4 19.5 18.0
3 17.7 18.9 20.4 17.3 18.3 19.2 19.3 17.9", header=TRUE)

apply(bw, 2, function(x) round(100*x/x[1], 1))
#     BW1   BW2   BW3   BW4   BW5   BW6   BW7   BW8
# 1 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0
# 2  98.4  98.5  96.6 100.6  97.9 102.6 102.6 101.1
# 3  96.2  96.4  98.6  99.4  97.9 101.6 101.6 100.6

或使用sweep()

round(sweep(bw, 2, unlist(bw[1,]), "/")*100, 1)
#     BW1   BW2   BW3   BW4   BW5   BW6   BW7   BW8
# 1 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0
# 2  98.4  98.5  96.6 100.6  97.9 102.6 102.6 101.1
# 3  96.2  96.4  98.6  99.4  97.9 101.6 101.6 100.6

甚至更簡單

round(100 * t(t(bw) / as.matrix(bw)[1,]), 1)
#     BW1   BW2   BW3   BW4   BW5   BW6   BW7   BW8
# 1 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0
# 2  98.4  98.5  96.6 100.6  97.9 102.6 102.6 101.1
# 3  96.2  96.4  98.6  99.4  97.9 101.6 101.6 100.6

在這種情況下,您實際上不需要apply

pctvals <- round(100.0 * bw[,1:ncol(bw)] / bw[,1], 2)

產量

  BW1    BW2    BW3   BW4    BW5    BW6    BW7    BW8
1 100 106.52 112.50 94.57 101.63 102.72 103.26  96.74
2 100 106.63 110.50 96.69 101.10 107.18 107.73  99.45
3 100 106.78 115.25 97.74 103.39 108.47 109.04 101.13

有一個在使用超級簡單的選擇mutate_atdplyr包:

library(dplyr)

working_df <-
  data.frame(BW1 = c(18.4, 18.1, 17.7),
             BW2 = c(19.6, 19.3, 18.9),
             BW3 = c(20.7, 20.0, 20.4))

variability_v2 <- function(df, column_numbers) {

  df %>% 
    mutate_at(vars(column_numbers), funs(var = round(100*(./first(.)), 1)))

}

variability_v2(working_df, 1:3)
#>    BW1  BW2  BW3 BW1_var BW2_var BW3_var
#> 1 18.4 19.6 20.7   100.0   100.0   100.0
#> 2 18.1 19.3 20.0    98.4    98.5    96.6
#> 3 17.7 18.9 20.4    96.2    96.4    98.6

此方法僅有2個(我認為是非常小的問題)是:

  • 如果您僅將單個列號輸入到函數中,則新列簡稱為“ var”
  • “ var”附加在列名之后,而不是之前

前者可以通過函數中的簡單“ if”語句處理,從而消除了僅指定一列的情況。 希望您不關心后者!

暫無
暫無

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

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