在 for 循环中将数据帧附加在一起

Posted

技术标签:

【中文标题】在 for 循环中将数据帧附加在一起【英文标题】:Append data frames together in a for loop 【发布时间】:2015-06-06 19:01:41 【问题描述】:

我有一个for loop,它会在每次迭代后生成一个数据框。我想将所有数据帧附加在一起,但发现很难。以下是我 正在尝试,请建议如何解决它:

d = NULL
for (i in 1:7) 

  # vector output
  model <- #some processing

  # add vector to a dataframe
  df <- data.frame(model)



df_total <- rbind(d,df)

【问题讨论】:

【参考方案1】:

你应该试试这个:

df_total = data.frame()
for (i in 1:7)
    # vector output
    model <- #some processing

    # add vector to a dataframe
    df <- data.frame(model)
    df_total <- rbind(df_total,df)

【讨论】:

它在单列中逐帧附加。如何将所有数据框附加到单独的列中? 使用 cbind() 代替 rbind() 使用cbind() 导致Error in data.frame(..., check.names = FALSE) : arguments imply differing number of rows: 0, 18262 您是否在重新执行循环之前重置了 df_total = data.frame()? 不重置,for loop 的每次迭代都会给出相同的行数【参考方案2】:

同样,马丁是正确的,但要使其正常工作,您必须从一个已经有至少一列的数据框开始

model <- #some processing
df <- data.frame(col1=model)

for (i in 2:17)

     model <- # some processing
     nextcol <-  data.frame(model)
     colnames(nextcol) <- c(paste("col", i, sep="")) # rename the comlum
     df <- cbind(df, nextcol)

【讨论】:

它可以工作,但会将数据附加到单个列中。我希望所有数据框都在单独的列中【参考方案3】:

不要在循环内这样做。列一个列表,然后在循环外将它们组合起来。

datalist = list()

for (i in 1:5) 
    # ... make some data
    dat <- data.frame(x = rnorm(10), y = runif(10))
    dat$i <- i  # maybe you want to keep track of which iteration produced it?
    datalist[[i]] <- dat # add it to your list


big_data = do.call(rbind, datalist)
# or big_data <- dplyr::bind_rows(datalist)
# or big_data <- data.table::rbindlist(datalist)

这是一种更像 R 的做事方式。它也可以大大加快,特别是如果您使用dplyr::bind_rowsdata.table::rbindlist 进行数据帧的最终组合。

【讨论】:

它也可以,但我想将所有列表写入单独的列 @Ibe 你真的应该编辑你的问题。提供示例数据和所需的输出(请参阅我在马丁的回答中的评论)并把rbind 排除在您的问题之外,因为所有rbind 所做的都是将行绑定在一起。 刚刚将代码中的rbind 替换为cbind。它有效,现在我将所有列表放在单独的列中 同样,如果这一步你觉得慢,试试dplyr::bind_cols() do.call(rbind, datalist) 是一种很好的写作方式rbind(datalist[[1]], datalist[[2]], datalist[[3]], ...)【参考方案4】:

在 Coursera 课程“R 编程简介”中,对这项技能进行了测试。 他们给所有学生 332 个单独的 csv 文件,并要求他们以编程方式组合几个文件来计算污染物的平均值。

这是我的解决方案:

  # create your empty dataframe so you can append to it.
  combined_df <- data.frame(Date=as.Date(character()),
                    Sulfate=double(),
                    Nitrate=double(),
                    ID=integer())
  # for loop for the range of documents to combine
  for(i in min(id): max(id)) 
    # using sprintf to add on leading zeros as the file names had leading zeros
    read <- read.csv(paste(getwd(),"/",directory, "/",sprintf("%03d", i),".csv", sep=""))
    # in your loop, add the files that you read to the combined_df
    combined_df <- rbind(combined_df, read)
  

【讨论】:

将它们全部读入一个列表然后将它们全部组合起来会更有效。【参考方案5】:

尝试使用rbindlist 方法而不是rbind,因为它非常非常快。

例子:

library(data.table)

##### example 1: slow processing ######

table.1 <- data.frame(x = NA, y = NA)
time.taken <- 0
for( i in 1:100) 
  start.time = Sys.time()
  x <- rnorm(100)
  y <- x/2 +x/3
  z <- cbind.data.frame(x = x, y = y)

  table.1 <- rbind(table.1, z)
  end.time <- Sys.time()
  time.taken  <- (end.time - start.time) + time.taken


print(time.taken)
> Time difference of 0.1637917 secs

####example 2: faster processing #####

table.2 <- list()
t0 <- 0
for( i in 1:100) 
  s0 = Sys.time()
  x <- rnorm(100)
  y <- x/2 + x/3

  z <- cbind.data.frame(x = x, y = y)

  table.2[[i]] <- z

  e0 <- Sys.time()
  t0  <- (e0 - s0) + t0


s1 = Sys.time()
table.3 <- rbindlist(table.2)
e1 = Sys.time()

t1  <- (e1-s1) + t0
t1
> Time difference of 0.03064394 secs

【讨论】:

【参考方案6】:

这里有一些 tidyverse 和自定义函数选项,它们可能会根据您的需要起作用:

library(tidyverse)

# custom function to generate, filter, and mutate the data:
combine_dfs <- function(i)
 data_frame(x = rnorm(5), y = runif(5)) %>% 
    filter(x < y) %>% 
    mutate(x_plus_y = x + y) %>% 
    mutate(i = i)


df <- 1:5 %>% map_df(~combine_dfs(.))
df <- map_df(1:5, ~combine_dfs(.)) # both give the same results
> df %>% head()
# A tibble: 6 x 4
       x      y x_plus_y     i
   <dbl>  <dbl>    <dbl> <int>
1 -0.973 0.673    -0.300     1
2 -0.553 0.0463   -0.507     1
3  0.250 0.716     0.967     2
4 -0.745 0.0640   -0.681     2
5 -0.736 0.228    -0.508     2
6 -0.365 0.496     0.131     3

如果你有一个需要合并的文件目录,你可以做类似的事情:

dir_path <- '/path/to/data/test_directory/'
list.files(dir_path)

combine_files <- function(path, file)
  read_csv(paste0(path, file)) %>% 
    filter(a < b) %>% 
    mutate(a_plus_b = a + b) %>% 
    mutate(file_name = file) 


df <- list.files(dir_path, '\\.csv$') %>% 
  map_df(~combine_files(dir_path, .))

# or if you have Excel files, using the readxl package:
combine_xl_files <- function(path, file)
  readxl::read_xlsx(paste0(path, file)) %>% 
    filter(a < b) %>% 
    mutate(a_plus_b = a + b) %>% 
    mutate(file_name = file) 


df <- list.files(dir_path, '\\.xlsx$') %>% 
  map_df(~combine_xl_files(dir_path, .))

【讨论】:

函数combine_files 对单个文件进行操作并且不与任何内容组合时,它似乎很奇怪......【参考方案7】:
x <- c(1:10) 

# empty data frame with variables ----

df <- data.frame(x1=character(),
                     y1=character())

for (i in x) 
  a1 <- c(x1 == paste0("The number is ",x[i]),y1 == paste0("This is another number ", x[i]))
  df <- rbind(df,a1)


names(df) <- c("st_column","nd_column")
View(df)

这可能是一个很好的方法......

【讨论】:

我没有对这篇文章投票(仅编辑了它的格式),但是从代码的角度和答案的角度来看,它都有一些问题。对于代码,&lt;- 不在函数调用中命名参数(例如c()),而是赋值运算符(命名参数使用=)。从答案的角度来看,在循环中调用rbind 与西蒙的答案基本相同。【参考方案8】:

对我来说,它非常简单。起初,我创建了一个空的data.frame,然后在每次迭代中我添加了一列。这是我的代码:

df <- data.frame(modelForOneIteration)
for(i in 1:10)
  model <- # some processing
  df[,i] = model

【讨论】:

【参考方案9】:

"""通过 Groupby 从唯一的 TF 生成多个 DataFrame"""

        i=0
        dfs_list=[]
        for i in range(i,len(df_CDL)):
            df = df_CDL[i]
            print(df,'Only 1 df_CDL')

            dfs= []
            for _, dataframe in df.groupby('TFs'):
                print('What is going on here?15',dataframe)
                dfs.append([dataframe])
            dfs_list.append([dfs])

#Index 任何你想要的数据框或遍历它们。随便..

       print('Test?10', dfs[1], 'Test?20')
       print('What is going on here? 1', dfs_list[5], 'What is 
       going on here again? 2')

【讨论】:

以上是关于在 for 循环中将数据帧附加在一起的主要内容,如果未能解决你的问题,请参考以下文章

附加在 for 循环中生成的 pandas 数据帧

如何在 for 循环中附加 pyspark 数据帧?

pyspark 在 for 循环下的每个进程之后附加非常大的多个数据帧(例如:在每日 ETL 之后附加)

如何将 for 循环中的 .pkl 文件附加到 for 循环中创建的 pandas 数据帧?

附加到数据帧中特定值的 for 循环中的向量

如何在for循环中将数据附加到空列表?