如何创建一个从更大的数据帧创建多个子集数据帧的循环?

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))

效果相同