如何编写 R 函数来创建基于多列的每个子组?
How to write R function to create every subgroup based on multiple columns?
我正在努力在 R 中创建一个函数,该函数将接受数据集和列,并输出由所有这 3 列过滤的数据集的每个排列。
我的数据集看起来像
structure(list(name = c("Peter Doe", "John Gary", "Elsa Johnson",
"Mary Poppins", "Jesse Bogart"), sex = c("Male", "Male", "Female",
"Female", "Male"), class = c("Honors", "Core", "Core", "Honors",
"Honors"), grade = c("A", "A", "A", "B", "C")), class = c("tbl_df",
"tbl", "data.frame"), row.names = c(NA, -5L))
我试着在这里形象化我的目标:
我希望根据这张地图所遵循的路径创建新变量(例如 male_honors_a <- 按这些列值过滤的数据集)我想我可以使用粘贴功能来做到这一点,但我在这里也不确定。但更重要的是,我正在努力解决如何将 for 循环放在能够根据列的唯一值进行过滤的函数中。
我编写了一个函数来单独创建每个子组,但无法弄清楚如何将它们组合在一起。
subgroups <- function(df, filters, group = "none", name = ""){
listofdfs <- list()
for (i in filters) {
subgroups <- unique(df[[i]])
for (j in subgroups){
x <- df[df[i] == j,]
listofdfs[[paste(name,j, sep = "")]] <- x
}
}
if (group != "none"){
return(listofdfs[[group]])
}
else {
return(listofdfs)}
}
subgroups(df, c("sex", "class", "grade"))
我希望 运行 subgroups(df, c("sex", "class"))
,我的输出将是数据帧列表:
list(male_honors, male_core, female_honors, female_core)
其中 male_honors
元素是
# A tibble: 2 × 4
name sex class grade
1 Peter Doe Male Honors A
2 Jesse Bogart Male Honors C
非常感谢任何帮助!
tidyr::nest()
直接执行此操作。请注意,对于 grouping/nesting 变量的每个组合,data
单元格中都会整齐地塞入一个 tibble。我通过 (a) 删除与分组无关的方面(如过滤器)和 (b) 使 groups
默认为空字符向量,对您的函数进行了一些修改,因此如果未传递任何内容,则不会对任何内容进行分组。
此外,名字(例如,男性荣誉)很容易通过变量值检索。这通常比从 变量名称 .
中检索值有用得多
这对您有用吗?
subgroups <- function(df, groups = character(0)) {
df |>
tidyr::nest(data = -groups)
}
> subgroups(ds, c("class", "sex"))
# # A tibble: 4 × 3
# sex class data
# <chr> <chr> <list>
# 1 Male Honors <tibble [2 × 2]>
# 2 Male Core <tibble [1 × 2]>
# 3 Female Core <tibble [1 × 2]>
# 4 Female Honors <tibble [1 × 2]>
> subgroups(ds, c("sex"))
# # A tibble: 2 × 2
# sex data
# <chr> <list>
# 1 Male <tibble [3 × 3]>
# 2 Female <tibble [2 × 3]>
> subgroups(ds)
# # A tibble: 1 × 1
# data
# <list>
# 1 <tibble [5 × 4]>
其他资源:tidyr 的 Nested data 插图
您可以创建用于过滤的列键。键的唯一性可用于循环遍历数据框的每个子集。这是一个解决方案,您的数据为 df
,所需的列表结果为 l
。
library(dplyr)
#make a key (constructed of 2 or more column values)
df<- df |> mutate(key = paste0(sex, "_", class))
#get the unqiue keys
keys<-unique(df$key)
#make an empty list
l<-list()
#loop through unique keys to filter your df, removing the key column
for(x in 1:length(keys)){
l[[x]]<-df[df$key ==keys[x],] |> select(!key)
}
#name list elements
names(l)<-tolower(keys)
# your desired result
l
写成一个函数,看起来像这样:
subgroups <- function(df, groups = character(0)){
#make a key vector
v <- df |> select(groups)
v <- do.call(paste, c(v, sep = "_"))
#get unqiue keys
keys<-unique(v)
#make an empty list
l<-list()
#loop through unique keys to filter, removing the key column
for(x in 1:length(keys)){
l[[x]]<-df[v %in% keys[x],] |> select(!key)
}
return(l)
}
#example call
subgroups(df, c("sex", "class"))
我正在努力在 R 中创建一个函数,该函数将接受数据集和列,并输出由所有这 3 列过滤的数据集的每个排列。
我的数据集看起来像
structure(list(name = c("Peter Doe", "John Gary", "Elsa Johnson",
"Mary Poppins", "Jesse Bogart"), sex = c("Male", "Male", "Female",
"Female", "Male"), class = c("Honors", "Core", "Core", "Honors",
"Honors"), grade = c("A", "A", "A", "B", "C")), class = c("tbl_df",
"tbl", "data.frame"), row.names = c(NA, -5L))
我试着在这里形象化我的目标:
我希望根据这张地图所遵循的路径创建新变量(例如 male_honors_a <- 按这些列值过滤的数据集)我想我可以使用粘贴功能来做到这一点,但我在这里也不确定。但更重要的是,我正在努力解决如何将 for 循环放在能够根据列的唯一值进行过滤的函数中。
我编写了一个函数来单独创建每个子组,但无法弄清楚如何将它们组合在一起。
subgroups <- function(df, filters, group = "none", name = ""){
listofdfs <- list()
for (i in filters) {
subgroups <- unique(df[[i]])
for (j in subgroups){
x <- df[df[i] == j,]
listofdfs[[paste(name,j, sep = "")]] <- x
}
}
if (group != "none"){
return(listofdfs[[group]])
}
else {
return(listofdfs)}
}
subgroups(df, c("sex", "class", "grade"))
我希望 运行 subgroups(df, c("sex", "class"))
,我的输出将是数据帧列表:
list(male_honors, male_core, female_honors, female_core)
其中 male_honors
元素是
# A tibble: 2 × 4
name sex class grade
1 Peter Doe Male Honors A
2 Jesse Bogart Male Honors C
非常感谢任何帮助!
tidyr::nest()
直接执行此操作。请注意,对于 grouping/nesting 变量的每个组合,data
单元格中都会整齐地塞入一个 tibble。我通过 (a) 删除与分组无关的方面(如过滤器)和 (b) 使 groups
默认为空字符向量,对您的函数进行了一些修改,因此如果未传递任何内容,则不会对任何内容进行分组。
此外,名字(例如,男性荣誉)很容易通过变量值检索。这通常比从 变量名称 .
中检索值有用得多这对您有用吗?
subgroups <- function(df, groups = character(0)) {
df |>
tidyr::nest(data = -groups)
}
> subgroups(ds, c("class", "sex"))
# # A tibble: 4 × 3
# sex class data
# <chr> <chr> <list>
# 1 Male Honors <tibble [2 × 2]>
# 2 Male Core <tibble [1 × 2]>
# 3 Female Core <tibble [1 × 2]>
# 4 Female Honors <tibble [1 × 2]>
> subgroups(ds, c("sex"))
# # A tibble: 2 × 2
# sex data
# <chr> <list>
# 1 Male <tibble [3 × 3]>
# 2 Female <tibble [2 × 3]>
> subgroups(ds)
# # A tibble: 1 × 1
# data
# <list>
# 1 <tibble [5 × 4]>
其他资源:tidyr 的 Nested data 插图
您可以创建用于过滤的列键。键的唯一性可用于循环遍历数据框的每个子集。这是一个解决方案,您的数据为 df
,所需的列表结果为 l
。
library(dplyr)
#make a key (constructed of 2 or more column values)
df<- df |> mutate(key = paste0(sex, "_", class))
#get the unqiue keys
keys<-unique(df$key)
#make an empty list
l<-list()
#loop through unique keys to filter your df, removing the key column
for(x in 1:length(keys)){
l[[x]]<-df[df$key ==keys[x],] |> select(!key)
}
#name list elements
names(l)<-tolower(keys)
# your desired result
l
写成一个函数,看起来像这样:
subgroups <- function(df, groups = character(0)){
#make a key vector
v <- df |> select(groups)
v <- do.call(paste, c(v, sep = "_"))
#get unqiue keys
keys<-unique(v)
#make an empty list
l<-list()
#loop through unique keys to filter, removing the key column
for(x in 1:length(keys)){
l[[x]]<-df[v %in% keys[x],] |> select(!key)
}
return(l)
}
#example call
subgroups(df, c("sex", "class"))