如何在 R 中读取和命名不同的 CSV 文件

Posted

技术标签:

【中文标题】如何在 R 中读取和命名不同的 CSV 文件【英文标题】:How to read and name different CSV files in R 【发布时间】:2016-10-27 12:04:28 【问题描述】:

我想对几个 csv 文件进行一些比较,所以我编写了这段代码来读取我拥有的不同 csv 文件:

path <- "C:\\data\\"
files <- list.files(path=path, pattern="*.csv")
for(file in files)

  perpos <- which(strsplit(file, "")[[1]]==".")
  assign(
    gsub(" ","",substr(file, 1, perpos-1)), 
    read.csv(paste(path,file,sep="")))

我的 csv 文件是这样的:

Start Time,End Time,Total,Diffuse,Direct,Reflected
04/09/14 00:01:00,04/09/14 00:01:00,2.221220E-003,5.797364E-004,0.000000E+000,1.641484E-003,
04/09/14 00:02:00,04/09/14 00:02:00,2.221220E-003,5.797364E-004,0.000000E+000,1.641484E-003,
04/09/14 00:03:00,04/09/14 00:03:00,2.221220E-003,5.797364E-004,0.000000E+000,1.641484E-003,
(...)

使用我的代码,R 正确地分离了所有文件,但它会为每个文件创建一个表格,在开头添加更多额外空间:

                 |Start Time       |End Time     |Total        |Diffuse      |Direct       |Reflected
04/09/14 00:01:00|04/09/14 00:01:00|2.221220E-003|5.797364E-004|0.000000E+000|1.641484E-003|NA
...

我该如何解决?

此外,考虑到每个文件的原始名称确实很长,是否可以使用文件的最后一个字母来命名每个data.frame?还是只是一个基数?

【问题讨论】:

R 工作正常:由于尾随逗号,您的 CSV 文件包含的列多于列标题。 您可能需要考虑将文件读入列表,而不是assign将它们发送到全局环境。例如:results &lt;- vector("list", length = length(files)); for(i in seq_along(files)) file &lt;- files[[i]]; results[[i]] &lt;- read.csv(paste0(path, file)) 如果要保留文件名,只需执行results[[file]] &lt;- read.csv(...)。如果它们的格式相同,你可以使用dplyr::bind_rows将它们联合起来。 他是说标题被移动了 1。一个简单的解决方法是运行 names(df) &lt;- c(names(df)[-1],"DROP"),然后运行 ​​df &lt;- df[,-"DROP"] @AmitKohli 这行不通,您首先必须将行名转换为列。使用 df %&gt;% rownames_to_column() %&gt;% setNames(c(colnames(.)[-1], 'DROP')) %&gt;% select(-DROP) 的 tibble/dplyr。但是,修复有问题的 CSV 文件似乎更干净。 我喜欢您的 dplyr 方法,但我的解决方案中没有任何内容涉及行名?同意修复有问题的 csv 文件更干净。刚才说这种方式可能更容易;) 【参考方案1】:

我建议使用 data.table 包 - 它更快,并且最终对于非空白列,它将这些转换为 NA(根据我的经验)。这是我为类似任务编写的一些代码:

read_func <- function(z) 
  dat <- fread(z, stringsAsFactors = FALSE)
  names(dat) <- c("start_time", "end_time", "Total", "Diffuse", "Direct", "Reflect")
  dat$start_tme <- as.POSIXct(strptime(dat$start_tme,
                    format = "%d/%m/%y %H:%M:%S"), tz = "Pacific/Easter")
  patrn <- "([0-9][0-9][0-9])\\.csv"
  dat$type <- paste("Dataset",gsub(".csv", "", regmatches(z,regexpr(patrn, z))),sep="")
  return(as.data.table(dat))


path <- ".//Data/" 
file_list <- dir(path, pattern = "csv")
file_names <- unname(sapply(file_list, function(x) paste(path, x, sep = "")))
data_list <- lapply(file_names, read_func)

dat <- rbindlist(data_list, use.names = TRUE) 

rm(path, file_list, file_names)

这将为您提供一个列表,其中每个项目作为相应文件名的 data.table。我假设所有文件名在扩展名之前都有一个三位数字,我用来为每个 data.table 分配一个变量type。您可以更改 patrn 以匹配您的特定用例。这样,当您将所有这些组合成一个 data.table dat 时,您始终可以根据类型进行排序/过滤。例如,如果您想为Dataset158datase222 绘制diffusedirect,您可以执行以下操作:

ggplot(data = dat[type == 'Dataset158' | type == 'Dataset222'], 
       aes(x = Diffuse, y = Direct)) + geom_point()

希望这会有所帮助!

【讨论】:

【参考方案2】:

您遇到了问题,因为您的 csv 文件末尾有一个空白列...这使您的数据以逗号结尾:

04/09/14 00:01:00,04/09/14 00:01:00,2.221220E-003,5.797364E-004,0.000000E+000,1.641484E-003,

这导致 R 认为您的数据由 7 列而不是 6 列组成。正确的解决方案是正确重新保存所有 csv 文件。否则,R 将看到 7 列但只有 6 个列名,并且在逻辑上会认为第一列是行名。您可以在这里应用我们为@konradrudolph 提供的补丁:

library(tibble) df %>% rownames_to_column() %>% setNames(c(colnames(.)[-1], 'DROP')) %>% select(-DROP)

其中df 是来自 csv 的数据。但是像这样的补丁可能会导致意想不到的结果……最好正确保存 csv 文件。

【讨论】:

以上是关于如何在 R 中读取和命名不同的 CSV 文件的主要内容,如果未能解决你的问题,请参考以下文章

在 Azure Blob 存储中覆盖后如何命名 csv 文件

如何从压缩文件中读取多个文件?

如何在 R 中的 read.csv(或其他读取函数)中“关闭”科学记数法?

Python pandas 保存多个不同名称的 CSV

如何在 R 中加入来自 2 个不同 csv 文件的数据?

如何读取CSV文件以及如何读取带有字符串数据项的CSV文件