将每个迭代保存在for循环中作为数据帧

时间:2020-08-03 18:47:26

标签: r

首先,是的,我已经研究了这个问题,是的,我已经看到了几个可以解决我问题的答案,但是我似乎无法将其应用于我的情况,所以我直接去找源头,希望有人能通过我的想法得到这个概念。我的数据显示出厚厚的头骨。这显然是一个小得多的例子。我试图过滤我们的行,其中包含来自Code_任一列中的向量的值,并将它们保存为每次迭代的数据框。现在,此代码在每次遍历中都添加了一个突变列,以显示代码向量中的哪个值已用于该过滤器。当然,这会导致很多重复,而且我仍然必须将输出分开,以将每次迭代放入自己的单独df中。

transaction <- c(1,2,3,4,5)
Code_1 <- c("QD","QK","QI","QE","QH")
Code_2 <- c("QE","QB","SA","QG","QC")
Code_3 <- c("QG","QH","DI","QK","QI")
Code_4 <- c("QK","QC","QD","QB","SA")

df <- data.frame(transaction, Code_1, Code_2, Code_3, Code_4)

codes <- c("QD","QH","SA")

test <- data.frame(NULL)

for(i in codes){
  tmp <- df %>% filter(Code_1 == i | Code_2 == i | Code_3 == i| Code_4 == i) %>% mutate(interation = 
i)
  test <- rbind(test, tmp)

}  

我得到一个输出,该输出捕获了我想要的所有行,但是我仍然必须根据变异列“ iteration”将它们操纵为单独的dfs。有什么方法可以丢失变异列并将每个迭代另存为df?它循环。我已经尝试了几个示例,并尝试了几个应用场景,但这是我唯一能够开始工作的东西。

很抱歉与输出混淆

在理想世界中,我希望每次迭代都输出唯一的tibble / df。我想要一个输出,就好像我刚刚运行了这样的东西,但是在数百个代码上运行了一千次。我不要清单。我想要唯一的个人输出。

QD <- df %>% filter(Code_1 == "QD" | Code_2 == "QD" | Code_3 == "QD"| 
Code_4 == "QD")
QH <- df %>% filter(Code_1 == "QH" | Code_2 == "QH" | Code_3 == "QH"| 
Code_4 == "QH")
SA <- df %>% filter(Code_1 == "SA" | Code_2 == "SA" | Code_3 == "SA"| 
Code_4 == "SA")

4 个答案:

答案 0 :(得分:3)

逐行增长帧在逻辑上是合理的,但可以可怕地缩放:添加每行,整个帧就被复制到内存中。这意味着当您有100行时,要添加1行,您的内存中前100行将为两次

解决方法是通常将行保存在list中,然后手动一步将它们合并

out <- list()
for(i in codes){
  tmp <- df %>% filter(Code_1 == i | Code_2 == i | Code_3 == i| Code_4 == i) %>% mutate(interation = i)
  out <- c(out, list(tmp))
}

out
# [[1]]
#   transaction Code_1 Code_2 Code_3 Code_4 interation
# 1           1     QD     QE     QG     QK         QD
# 2           3     QI     SA     DI     QD         QD
# [[2]]
#   transaction Code_1 Code_2 Code_3 Code_4 interation
# 1           2     QK     QB     QH     QC         QH
# 2           5     QH     QC     QI     SA         QH
# [[3]]
#   transaction Code_1 Code_2 Code_3 Code_4 interation
# 1           3     QI     SA     DI     QD         SA
# 2           5     QH     QC     QI     SA         SA
do.call(rbind, out)
#   transaction Code_1 Code_2 Code_3 Code_4 interation
# 1           1     QD     QE     QG     QK         QD
# 2           3     QI     SA     DI     QD         QD
# 3           2     QK     QB     QH     QC         QH
# 4           5     QH     QC     QI     SA         QH
# 5           3     QI     SA     DI     QD         SA
# 6           5     QH     QC     QI     SA         SA

我应该补充一点,我保留了for循环,使其与您的起始代码相似; Rui提出的使用lapply的建议是朝“更好”方向迈出的一步。

答案 1 :(得分:3)

这是一种lapply解决方案,不需要tmp data.frame。

codes <- c("QD","QH","SA")

test <- lapply(codes, function(i){
  df %>% 
    filter(Code_1 == i | Code_2 == i | Code_3 == i| Code_4 == i) %>% 
    mutate(interation = i)
})
test

test <- do.call(rbind, test)
test
#  transaction Code_1 Code_2 Code_3 Code_4 interation
#1           1     QD     QE     QG     QK         QD
#2           3     QI     SA     DI     QD         QD
#3           2     QK     QB     QH     QC         QH
#4           5     QH     QC     QI     SA         QH
#5           3     QI     SA     DI     QD         SA
#6           5     QH     QC     QI     SA         SA

答案 2 :(得分:1)

我们可以使用rowSums

创建一个逻辑表达式
library(dplyr)
library(purrr)
map(codes, ~ 
       df %>% 
         filter(rowSums(select(., 
                starts_with('Code')) == .x) > 0) %>%
             mutate(interaction = .x)
       )
#[[1]]
#  transaction Code_1 Code_2 Code_3 Code_4 interaction
#1           1     QD     QE     QG     QK          QD
#2           3     QI     SA     DI     QD          QD

#[[2]]
#  transaction Code_1 Code_2 Code_3 Code_4 interaction
#1           2     QK     QB     QH     QC          QH
#2           5     QH     QC     QI     SA          QH

#[[3]]
#  transaction Code_1 Code_2 Code_3 Code_4 interaction
#1           3     QI     SA     DI     QD          SA
#2           5     QH     QC     QI     SA          SA

答案 3 :(得分:0)

一个tidyverse解决方案。我们将命名输入向量,以使输出test实际上是根据需要命名的小标题列表

codes <- c("QD","QH","SA")
names(codes) <- codes

library(dplyr)
library(purrr)

test <- purrr::map(codes, function(i){
  df %>% 
    rowwise() %>%
    filter(i %in% c_across(Code_1:Code_4)) %>% 
    mutate(interation = i) %>%
    ungroup
  
})

# test has everything but they are all named so ...

test$QD
#> # A tibble: 2 x 6
#>   transaction Code_1 Code_2 Code_3 Code_4 interation
#>         <dbl> <chr>  <chr>  <chr>  <chr>  <chr>     
#> 1           1 QD     QE     QG     QK     QD        
#> 2           3 QI     SA     DI     QD     QD