簡體   English   中英

具有多個變量的用戶定義函數? / 對一系列命名列進行操作的函數(而不是按數字索引)?

[英]User-defined functions with multiple variables? / Function to operate on a range of named columns (instead of indexed by number)?

我經常想對數據框中的一組或一系列列執行函數。 最常見的是,我想取均值一系列具有共同的前綴列(在這個例子玩具, VarA.VarB.VarC.

ID<-c(1:300) #participant ID column, N=300
VarA.1<-sample(x = 0:50,size = 300, replace = TRUE)
VarA.2<-sample(x = 0:50,size = 300, replace = TRUE)
VarA.3<-sample(x = 0:50,size = 300, replace = TRUE)
VarB.1<-sample(x = 0:30,size = 300, replace = TRUE)
VarB.2<-sample(x = 0:30,size = 300, replace = TRUE)
VarB.3<-sample(x = 0:30,size = 300, replace = TRUE)
VarC.1<-sample(x = 0:10,size = 300, replace = TRUE)
VarC.2<-sample(x = 0:10,size = 300, replace = TRUE)
VarC.3<-sample(x = 0:10,size = 300, replace = TRUE)


df<-data.frame(ID,VarA.1,VarA.2,VarA.3,
               VarB.1,VarB.2,VarB.3,
               VarC.1,VarC.2,VarC.3) 
rm(ID,VarA.1,VarA.2,VarA.3,
   VarB.1,VarB.2,VarB.3,
   VarC.1,VarC.2,VarC.3)

我通常有一的變量,所以我不能記住列數。 假設我想取以VarA.開頭的所有列的平均值VarA. 並將其放入名為VarA的新列中。 這是我通常的做法:

x<-which(colnames(df)=="VarA.1")
y<-which(colnames(df)=="VarA.3")
df$VarA<-rowMeans(df[, c(x:y)])

也許我太挑剔了,但鑒於我必須在某些腳本中執行此操作(或非常類似的操作)超過 20 次,它看起來非常混亂和笨拙,而且很難記住:我必須挖掘一個之前的文件,然后復制和粘貼並仔細更改所有值以適合我當前的數據集。 我真的很想把它變成一個函數,但我對用戶定義的函數不是很熟悉,而且我很難弄清楚如何處理多個變量。

我嘗試的方法是:

colmeans <- function(x,y,df,meancol) {
  first<-which(colnames(df)==x)
  last<-which(colnames(df)==y)
  df$meancol<-rowMeans(df[, c(first:last)])
}
colmeans("VarA.1","VarA.3",df,"VarA")

我本可以發誓它在某一時刻有效,但我失去了它,我不記得我改變了什么。 我錯過了什么?

我也樂於接受有關如何提高此過程效率的其他想法。

我們可以使用split.default

lst1 <- lapply(split.default(df[-1], sub("\\.\\d+$", "", names(df)[-1])),
         rowMeans, na.rm = TRUE)
df[paste0(names(lst1), "_Mean")] <- lst1

-輸出

head(df, 3)
  ID VarA.1 VarA.2 VarA.3 VarB.1 VarB.2 VarB.3 VarC.1 VarC.2 VarC.3 VarA_Mean VarB_Mean VarC_Mean
1  1     25     40     27      6      9      2      3      1      0  30.66667  5.666667  1.333333
2  2     43     16     26     27      7      5      2     10      5  28.33333 13.000000  5.666667
3  3     14     34     38      9     10      7      3      9      9  28.66667  8.666667  7.000000

或者使用tidyverse

library(dplyr)
library(tidyr)
df %>%
    pivot_longer(cols = -ID, names_to = ".value",
        names_pattern = "^([^.]+)\\.\\d+") %>% 
    group_by(ID) %>%
    summarise(across(everything(), mean, na.rm = TRUE, 
          .names = "{.col}_Mean"), .groups = 'drop') %>%
  left_join(df)

您是否正在尋找這樣的解決方案?

library(dplyr)
df %>% 
  mutate(across(starts_with("VarA"), mean, .names = "mean_{.col}"))

輸出:

+   head()
  ID VarA.1 VarA.2 VarA.3 VarB.1 VarB.2 VarB.3 VarC.1 VarC.2 VarC.3 mean_VarA.1 mean_VarA.2
1  1     41     37      7      0     14      1     10      7      0    23.97667    24.73667
2  2     50     36     20     16     29      7      0     10      9    23.97667    24.73667
3  3      2      5     43     20     24      9      5      8      8    23.97667    24.73667
4  4      9     39     41     15     21      5      9      6      3    23.97667    24.73667
5  5     38     25     37     20     19     24      6      5      4    23.97667    24.73667
6  6     12     27     47     28     14     14     10      5      2    23.97667    24.73667
  mean_VarA.3
1    26.16667
2    26.16667
3    26.16667
4    26.16667
5    26.16667
6    26.16667

暫無
暫無

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

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