【问题标题】:For loop within function to generate subsets of dataframes函数内循环以生成数据帧的子集
【发布时间】:2018-06-18 22:04:01
【问题描述】:

我正在尝试编写一个接受数据帧的函数,然后在 for() 循环中生成子数据帧。作为第一步,我尝试了以下方法:

dfcreator<-function(X,Z){
  for(i in 1:Z){
  df<-subset(X,Stratum==Z)    #build dataframe from observations where index=value
  assign(paste0("pop", Z),df) #name dataframe
 }
}

但是,这不会将任何内容保存到内存中,当我尝试指定 return() 时,我仍然没有得到我需要的东西。作为参考,我正在使用 瑞典数据集(RStudio 原生)。

根据 Melissa 的建议进行编辑!

我尝试实现以下代码:

sampler <- function(df, n,...) {
  return(df[sample(nrow(df),n),])
}

sample_list<-map2(data_list, stratumSizeVec, sampler)

其中 stratumSizeVec 是 1X7 df,data_list 是七个 df 的列表。当我这样做时,我会在样本列表中得到七个样本,它们的大小都等于stratumSizeVec[1]。为什么map2没有按以下方式输入

sampler(data_list$pop0,stratumSizeVec[1])
sampler(data_list$pop1,stratumSizeVec[2])

...

sampler(data_list$pop6,stratumSizeVec[7])

此外,有没有办法将 map2 函数“嵌套”在 lapply 中?

【问题讨论】:

  • 从长远来看,像这样创建一堆变量会使它们更难使用。最好使用split() 之类的东西来创建data.frames 列表。这将使 R 中的许多函数更快乐。在函数中创建的变量将不存在于该函数之外。最好将返回值的函数编写为适当的函数式语言。同样,从长远来看,它会让事情变得更容易。
  • list2env(setNames(split(X,X$Stratum),paste0("pop",unique(X$Stratum))))

标签: r for-loop subset


【解决方案1】:

我很困惑为什么您从未在循环中的任何地方实际使用i。看起来您正在创建 Z 数据集的副本 Stratum == Z - 这就是您所追求的吗?

至于您的代码,我将使用以下代码:

data_list <- split(df, df$Stratum)
names(data_list) <- paste0("pop", sort(unique(df$Stratum)))

这并没有定义函数,我们调用的是 base-R 函数(即split),它根据某个向量(这里,我们使用df$Stratum)分割数据帧。结果是一个数据帧列表,每个数据帧都有一个单独的值Stratum

从行中随机抽样

sampled_data <- lapply(data_list, function(df, n,...) { # n is the number of rows to take, the dots let you send other information to the `sample` function.
  df[sample(nrow(df), n, ...),]
},
n = 5,
replace = FALSE # this is default, but the purpose of using the ... notation is to allow this (and any other options in the `sample` function) to be changed.
)

也可以单独定义函数:

sampler <- function(df, n,...) {
  df[sample(nrow(df), n, ...),]
}
sampled_data <- lapply(data_list, sampler, n = 10) # replace 10 with however many samples you want.

purrr:map2 方法

按照定义,sampler函数不需要修改,将第一个列表(data_list)的每个元素放入sampler的第一个参数中,第二个“列表”的对应元素(sampleSizeVec)为放入第二个参数。

library(purrr)
map2(data_list, sampleSizeVec, sampler, replace = FALSE) # replace = FALSE not needed, there as an example only.

【讨论】:

  • 感谢您的回复,梅丽莎!因此,使用上面的 split() 函数,我列出了我的数据帧(每个层一个)。然后我可以使用 lapply 对每个数据帧进行采样()吗?我尝试包含索引的原因是因为我需要使用以下内容从样本大小向量中访问元素: samp1 其中 i 是样本大小向量的索引。最终,我想要以下内容:lapply(data_list, sample())
  • 试试lapply(data_list, sample)
  • 再次感谢您,梅丽莎。当我做sample_list&lt;-lapply(data_list, sample, size=strata_data$nh,replace=FALSE) 时,我得到的“样本”等于上面的data_list。如何从 strata_data 数据框中访问正确的大小?例如,第一个样本需要strata_data$nh[1],第二个样本需要strata_data$nh[2]
  • 谢谢!所以你说我应该写一个函数sampler,它将数据帧pop1作为输入以及向量strata_data$nh[1]然后取正确的样本,然后有sample_data&lt;-lapply(data_list,sampler)? ---------我刚看到你编辑 - 谢谢,我现在就看看!
  • 所以澄清一下:在您编辑的代码中,function(df,n,...) 是一个函数,它从data_list 中的每个数据帧中获取 n 个样本? indices 到底是什么?感谢您的所有跟进!
猜你喜欢
  • 1970-01-01
  • 2021-04-26
  • 1970-01-01
  • 2020-04-03
  • 2013-11-21
  • 1970-01-01
  • 1970-01-01
  • 2016-09-25
相关资源
最近更新 更多