如何创建一个从更大的数据帧创建多个子集数据帧的循环?
How to create a loop which creates multiple subset dataframes from a larger data frame?
我正在尝试在 R 中创建代码,该代码将立即识别特定列的值,找到具有该值的所有行,并从所有这些行中提取数据,包括与这些行相交的所有其他列新的数据框。我希望对基列中的每个不同值重复此操作。例如:
mydata <- data.frame(x = c(1,2,3), y = c('a','b','c'), z = c('red','red','yellow'))
colors <- list(mydata$z)
for (i in 1:length(colors)) {
assign(paste0("mydata_",i), subset(mydata, z == colors[[i]]))
}
这是我最近的尝试,但无法正常工作。目标是在此示例中拥有 2 个名为“mydata_red”和“my_data_yellow”的新数据帧。每个只包含匹配的行
您的代码运行良好。只需删除 list
即可创建颜色名称向量而不是列表。如果您只想要不同的值,请使用 unique
.
mydata <- data.frame(x = c(1,2,3), y = c('a','b','c'), z = c('red','red','yellow'))
colors <- unique(mydata$z)
for (i in 1:length(colors)) {
assign(paste0("mydata_",i), subset(mydata, z == colors[[i]]))
}
使用 assign
将一个框架或列表拆分为多个对象是 anti-pattern,并且很少改进将所有框架保存在 list
中的首选方法。请参阅有关此主题的 How do I make a list of data frames? 个讨论。一个前提是,当你对列表中的一个框架做某事时,你很可能会做一些与框架列表的其他元素非常相似的事情,并使用 lapply
处理列表并将你的方法概括为几乎无法提供更清洁的解决方案等。
要获得这些数据,就像拆分一样简单:
LOF <- split(mydata, mydata$z)
LOF ## <- "List Of Frames", perhaps not the most awesome name?
# $red
# x y z
# 1 1 a red
# 2 2 b red
# $yellow
# x y z
# 3 3 c yellow
正如 jay.sf 的评论所建议的,此 可以 用于将此帧列表转换为单个对象。虽然我一般不鼓励这样做,但也许它最适合您的 use-case.
names(LOF) <- paste0("mydata_", names(LOF))
list2env(LOF, envir = globalenv())
# <environment: R_GlobalEnv> ### this can be safely ignored
ls()
# [1] "LOF" "mydata" "mydata_red" "mydata_yellow"
mydata_red
# x y z
# 1 1 a red
# 2 2 b red
在 tidyverse 中:
mydata %>% group_by(z) %>% group_map(~.x %>% mutate(z=.y$z))
[[1]]
# A tibble: 2 × 3
x y z
<dbl> <chr> <chr>
1 1 a red
2 2 b red
[[2]]
# A tibble: 1 × 3
x y z
<dbl> <chr> <chr>
1 3 c yellow
~.x %>% mutate(z = .y$z)
乍一看可能有点奇怪。 ~
创建一个 lambda(函数)。默认情况下,group_map
的 .f
参数采用一个必需参数和一个可选参数。必需的参数默认命名为 .x
,它包含包含当前组的输入数据框的子集。同样,可选参数 .y
包含定义当前组的单个行。 group_map
将 .f
定义的函数依次应用于每组输入数据框,并 returns 列表中的结果。
mydata %>% group_by(z) %>% group_map(~.x %>% bind_cols(.y))
效果相同
我正在尝试在 R 中创建代码,该代码将立即识别特定列的值,找到具有该值的所有行,并从所有这些行中提取数据,包括与这些行相交的所有其他列新的数据框。我希望对基列中的每个不同值重复此操作。例如:
mydata <- data.frame(x = c(1,2,3), y = c('a','b','c'), z = c('red','red','yellow'))
colors <- list(mydata$z)
for (i in 1:length(colors)) {
assign(paste0("mydata_",i), subset(mydata, z == colors[[i]]))
}
这是我最近的尝试,但无法正常工作。目标是在此示例中拥有 2 个名为“mydata_red”和“my_data_yellow”的新数据帧。每个只包含匹配的行
您的代码运行良好。只需删除 list
即可创建颜色名称向量而不是列表。如果您只想要不同的值,请使用 unique
.
mydata <- data.frame(x = c(1,2,3), y = c('a','b','c'), z = c('red','red','yellow'))
colors <- unique(mydata$z)
for (i in 1:length(colors)) {
assign(paste0("mydata_",i), subset(mydata, z == colors[[i]]))
}
使用 assign
将一个框架或列表拆分为多个对象是 anti-pattern,并且很少改进将所有框架保存在 list
中的首选方法。请参阅有关此主题的 How do I make a list of data frames? 个讨论。一个前提是,当你对列表中的一个框架做某事时,你很可能会做一些与框架列表的其他元素非常相似的事情,并使用 lapply
处理列表并将你的方法概括为几乎无法提供更清洁的解决方案等。
要获得这些数据,就像拆分一样简单:
LOF <- split(mydata, mydata$z)
LOF ## <- "List Of Frames", perhaps not the most awesome name?
# $red
# x y z
# 1 1 a red
# 2 2 b red
# $yellow
# x y z
# 3 3 c yellow
正如 jay.sf 的评论所建议的,此 可以 用于将此帧列表转换为单个对象。虽然我一般不鼓励这样做,但也许它最适合您的 use-case.
names(LOF) <- paste0("mydata_", names(LOF))
list2env(LOF, envir = globalenv())
# <environment: R_GlobalEnv> ### this can be safely ignored
ls()
# [1] "LOF" "mydata" "mydata_red" "mydata_yellow"
mydata_red
# x y z
# 1 1 a red
# 2 2 b red
在 tidyverse 中:
mydata %>% group_by(z) %>% group_map(~.x %>% mutate(z=.y$z))
[[1]]
# A tibble: 2 × 3
x y z
<dbl> <chr> <chr>
1 1 a red
2 2 b red
[[2]]
# A tibble: 1 × 3
x y z
<dbl> <chr> <chr>
1 3 c yellow
~.x %>% mutate(z = .y$z)
乍一看可能有点奇怪。 ~
创建一个 lambda(函数)。默认情况下,group_map
的 .f
参数采用一个必需参数和一个可选参数。必需的参数默认命名为 .x
,它包含包含当前组的输入数据框的子集。同样,可选参数 .y
包含定义当前组的单个行。 group_map
将 .f
定义的函数依次应用于每组输入数据框,并 returns 列表中的结果。
mydata %>% group_by(z) %>% group_map(~.x %>% bind_cols(.y))
效果相同