【问题标题】:How to loop through multiple variables and filter data to produce multiple dataframes?如何遍历多个变量并过滤数据以产生多个数据帧?
【发布时间】:2021-02-20 03:41:38
【问题描述】:

我有一个大约 1000 行的数据框 df,其中包含以下列:

df$ID<- c("ab11", "ab12" ...) #about 1000 rows
df$ID1<-numbers ranging from 1 to 20k # for all intense and purposes this can be treated as class 'factor'
df$Acol<- #numbers ranging from 1 to 1000
df$Bcol<- #numbers ranging from 0 to 1

以下列表在每个列表中为我提供了 12 个值:

A<- seq(50,600,by=50)
B<- seq(0.2,1,by=0.75)

我正在尝试做两件事:

  1. 我想通过使用列表 A 和 B 的各种组合过滤原始数据集来创建数据帧。所以 144 个数据帧。
  2. 拥有这些数据帧后,我想一次组合 3 个数据帧,看看 ID 的频率是否与主数据帧 x 匹配,如果匹配,则获取匹配数据帧的组合信息。

所以对于 1,这是我的方法:

df_50_0.2<-subset(df, df$Acol>=50 & df$Bcol>=0.2)

我不能把它写出 144 次——我需要一个循环。我尝试了嵌套循环,但这并没有给我 A 和 B 的所有组合,所以我尝试了一个 while 循环。

这是我的代码:

i<-50
while (i<550) {
   for (j in B) {
      assign(paste("df","_",as.character(i),"_",as.character(j)), df %>% 
      filter (Acol>=i) %>% 
      filter(Bcol>=j),envir=.GlobalEnv
   i<-i+50
  }}   

这给了我想要的结果,除了它没有根据 B 拆分数据帧。所以输出类似于我刚刚过滤具有 A 值的数据时的输出。

对于第二部分,我需要一次遍历三个数据帧的所有可能组合。这是我的代码:

df.final<-rbind (df_50_0.2,df_100_0.25,df_150_0.5)
tmp<-subset(table(df.final$ID),!(table(df.final$ID) %in% table(x$ID))

我希望上述内容处于循环状态。如果 tmp 有任何值,我不希望它成为输出。如果为 0,即与主数据帧 x 中的 ID 频率完美匹配,我希望将其写入。所以像下面这样的循环?我希望迭代检查所有可能的组合,以得出与主数据帧 x ID 频率完美匹配的组合:

if tmp = NULL
tmp
else rm(tmp)

非常感谢任何帮助。也欢迎提供 python 解决方案!

以下链接中提供但针对两列进行修改的解决方案可能会有所帮助Filter loop to create multiple data frames

【问题讨论】:

  • 您能提供一个最小的可重现示例吗?尝试制作一个玩具示例,帮助我们了解您想要做什么。
  • 您是否尝试创建重叠数据框?命令df_50_0.2&lt;-subset(df, df$A&gt;=50 &amp; df$B&gt;=0.2) 将包含所有观察结果。下一个将包括 A 和 B 两个较小组中的所有组以外的所有组,依此类推。
  • @dcarlson,是的。数据框将重叠
  • @JoaoPedroMacalos,以下链接中提供的解决方案,但针对两列进行了修改可能会有所帮助stackoverflow.com/questions/54679034/…

标签: python r dataframe for-loop while-loop


【解决方案1】:

这不是一个完整的答案,但它代表了思考问题的不同方式。首先,我们需要一个可重现的样本。我将省略您的前两列,但修改示例以包含它们并不难。

set.seed(42)
df <- data.frame(A=runif(200) * 1000 + 1, B=runif(200))
Aint <- seq(50, 600, by=50)
Bint <- seq(0.2, 1, by=0.05)
comb <- expand.grid(Aint=Aint, Bint=Bint)

这为您提供了一个包含 200 个观察值和 A 列和 B 列的数据框。然后我们创建区间(称为 AintBint,因此我们不会将它们与 df$Adf$B 混淆。下一个行创建这些间隔的所有可能组合 - 204(不是 144,因为 Bint 有 17 个值)。

现在我们需要定义您的组并为每个组生成标签:

groups <- apply(comb, 1, function(x)   df$A > x[1] & df$B > x[2])
labels <- paste("df", comb[, 1], comb[, 2], sep="_")

groups 是一个 200 x 204 的逻辑矩阵,因此每一列都定义了一个比较。这 第一组定义为df[groups[, 1], ],第二组定义为df[groups[, 2], ]。这些比较的标签是labels[1]labels[2]

由于您的组是重叠的,下一步将在每组三个中创建多个数据副本。 204组的组合数,一次取3个,为1,394,204。下面生成代码来创建 3 个数据帧的不同组合:

allcombos <- combn(204, 3, simplify=TRUE)
for (i in 1:5) {
    dfno <- allcombos[, i]
    df.final <- rbind(df[groups[, dfno[1]], ], df[groups[, dfno[2]], ], df[groups[, dfno[3]], ])
    lbl <- labels[dfno]
    
}

下一步涉及subset(table(df.final$ID),!(table(df.final$ID) %in% table(x$ID)),但该行不符合您的建议。它创建了每个 ID 在df.final 中出现的次数的频率表和主数据框x 的表。 %in% 语句处理df.final 中的每个频率,并检查它是否与master 中ANY ID 的频率匹配。所以我没有包含将当前df.final 写入列表的逻辑语句或代码。

【讨论】:

  • 这是一个非常好的方法 - 无需复制数据并弄乱工作空间。
  • 谢谢@dcarlson。这很强大。不知道如何从这里开始。我想做 df.final
  • @dcarlson,我还修改了我原来的问题,希望为第二部分提供清晰的说明
  • @dcarlson,再次感谢。你的 for 循环中的 allcombos 是什么?因此,我确实在尝试创建每个 ID 在 df.final 中出现的次数的频率表和主数据框 x 的表。然后使用 %in% 语句处理 df.final 中的每个频率,并检查它是否与 master 中任何 ID 的频率匹配。如果完全匹配,(即如果我将它保存到 tmp 并且 tmp 为空),我想写出 tmp.如果它们不匹配,我希望删除 tmp。
  • @dcarlson,如果您创建的“组”有 4 列,我会这样做:df.final
猜你喜欢
  • 1970-01-01
  • 2021-08-25
  • 1970-01-01
  • 1970-01-01
  • 2021-12-25
  • 2022-11-03
  • 2019-03-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多