【问题标题】:Looping together extracted CSVs into one dataframe将提取的 CSV 循环到一个数据帧中
【发布时间】:2021-10-14 05:06:09
【问题描述】:

我有一些来自 s3 存储桶的 CSV 文件,我想将它们合并到一个数据帧中。出于本练习的目的,让我们使用存储在名为script_results 的字符向量中的这五个文件:

[1] "05162021-test-america-distributed-a-script_results-03-16-2021-404806813.csv"
[2] "07262021-test-america-distributed-a-script_results-04-26-2021-534691276.csv"
[3] "09202021-test-arizona-script_results-08-19-2020--08-31-2020-354731384.csv"
[4] "09222021-test-wisconsin-script_results-08-19-2020--08-20-2020-068472211.csv"
[5] "01062021-av-america-script_results-01-5-2021-038680844.csv"

第一步是从每个 CSV 中提取数据,使用以下内容(以上面列出的第一个 .csv 为例):

extract_data <- aws.s3::s3read_using(read.csv, bucket = "test-america", object = "03162021-test-america-distributed-a-script_results-03-16-2021-404806813.csv")

然后,它会使用 plyr 包中的 rbind.fill 函数将这些解压缩的 CSV 中的每一个连续绑定到一个数据帧中。

因此,最终结果将是来自script_results 下列出的五个 CSV 的所有五个数据集使用rbind.fill 函数合并在一起。

我还应该注意,我每天都会收到一个新文件,所以我想不断调整这些新文件到达我的 S3 存储桶。

这可能吗?

编辑:使用@r2evans cmets

L <- lapply(script_results, function(fn) aws.s3::s3read_using(read.csv, bucket="bucket-name", object=fn))

这行得通。但问题是当我尝试使用以下方法将其转换为数据框时:

t<- do.call(rbind.data.frame, L)

我收到以下错误:

Error in (function (..., deparse.level = 1, make.row.names = TRUE, stringsAsFactors = FALSE,  : 
  numbers of columns of arguments do not match

【问题讨论】:

  • plyr::rbind.filldplyr::bind_rowsdata.table::rbindlist 或基本do.call(rbind, ...) 通常都可以正常工作,只要所有框架具有相同的列名且顺序相同。其中一些函数更擅长处理列差异。所有这些都以将所有帧读取到帧列表中,然后在最后将它们组合成单个帧的前提开始;请注意,迭代增长帧的缩放比例很差,并且对于更大的数据,它需要的时间比您想要的要长得多。见stackoverflow.com/a/24376207/3358227
  • @r2evans 谢谢。我使用rbind.fill 的原因是因为列名不会在文件之间保持一致。有些将具有相同的列名,有些则不会。那么这在代码形式中实际上是什么样的呢?
  • 这里没有足够的信息让我可以肯定地说。一些样本:dplyr::bind_rows(list(data.frame(a=1,b=2),data.frame(a=11,d=12)))data.table::rbindlist(list(data.frame(a=1,b=2),data.frame(a=11,d=12)),use.names=TRUE,fill=TRUE) 都产生相似的输出。
  • @r2evans 您还需要哪些额外信息?我想确保我正在整理一个有人可以真正回答的问题
  • 如果您查看我在第一条评论中包含的链接,除其他外,它建议lapply(my_files, read.csv)。将其转换为您的问题,我认为应该是L &lt;- lapply(script_results, function(fn) aws.s3::s3read_using(read.csv, bucket=..., object=fn)) 来获取您的框架列表;从那里应用将它们全部组合的选项之一。

标签: r


【解决方案1】:

我不熟悉 aws.s3 中的函数,但这是基本概念,也许您可​​以将其翻译为适合您的情况。

library(plyr)

# your old dataframe of bucket data from "yesterday" with a field that holds the
# name of each csv that a given record is associated with
df_old <- data.frame(otherdata = c(1,2,3), csv = "from_a_previous_bucket_dump.csv")

# get the names of files in the bucket "today"
scriptresults <- list.files()

# only read csvs that aren't already in df_old$csv
fs_new <- setdiff(scriptresults, df_old$csv)

# Read a csv and add it name as a new field
read_csv_filename <- function(filename){
  ret <- read.csv(filename)
  ret$csv <- filename
  return(ret)
}
fsl <- lapply(fs_new, read_csv_filename)

df_new <- plyr::rbind.fill(c(fsl, list(df_old)))

read_csv_filename() 来自When importing CSV into R how to generate column with name of the CSV?

【讨论】:

  • 谢谢,但我对此感到很困惑。你能解释一下df_old发生了什么吗?
  • 当然。根据我的理解,您的问题的一项规定是确保您没有从已并入数据集的存储桶中加载相同的 csv(即,从您之前运行此脚本的时间开始)。 df_old 是我的工作数据集示例(已从存储桶编译的数据)。如果这没有意义,请告诉我。
  • 那么otherdata = c(1,2,3) 是什么意思? 1、2、3代表什么?
  • 我试图(不好地)说明您的工作数据集是一个 data.frame,其中每一行包含任意数量的列和行,每一行都是来自 csv 的记录。每一行数据的原始文件名存储在df$csv中。这很重要,因为它是避免df_new 中重复数据的基础,当您在将来运行此脚本以将存储桶中的新数据与您的工作数据集结合时。
  • 也许我应该问一个问题来澄清我的假设。存储桶是否有可能同时包含新数据(不在您的工作 df 中)和旧数据(已经在您的工作 df 中)但不是所有旧数据?
猜你喜欢
  • 2016-10-05
  • 2021-10-24
  • 2019-08-07
  • 1970-01-01
  • 2013-03-07
  • 2015-02-07
  • 2020-12-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多