如何在 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 <- vector("list", length = length(files)); for(i in seq_along(files)) file <- files[[i]]; results[[i]] <- read.csv(paste0(path, file))
如果要保留文件名,只需执行results[[file]] <- read.csv(...)
。如果它们的格式相同,你可以使用dplyr::bind_rows
将它们联合起来。
他是说标题被移动了 1。一个简单的解决方法是运行 names(df) <- c(names(df)[-1],"DROP")
,然后运行 df <- df[,-"DROP"]
@AmitKohli 这行不通,您首先必须将行名转换为列。使用 df %>% rownames_to_column() %>% setNames(c(colnames(.)[-1], 'DROP')) %>% 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
时,您始终可以根据类型进行排序/过滤。例如,如果您想为Dataset158
和datase222
绘制diffuse
与direct
,您可以执行以下操作:
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 文件