[英]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.