将具有时间序列的大型混合 CSV 导入 R

Importing a large mixed CSV with time series into R

我是 R 的初学者,一直在网站上寻找答案,但没有解决我的具体问题。

基本上我需要导入大约 15 个 CSV 文件并处理每个文件(绘图和分析)。它们每个都包含数千个条目,并且是时间序列,每个都有 15-20 个样本。格式是这样的,顶部有日期,顶行有我需要保留的其他列名,然后是需要通过导入保留的百分比数字。

到目前为止,我已经了解了如何导入、处理和清理,但所有内容都以字符形式存储,我丢失了有效数字。

我真的希望得到一些关于工作流程和合适的导入处理函数的建议,因为我需要保留日期和名称的第一列(我可以将其存储为索引向量或数据框),然后处理数据本身(以便我可以单独绘制或汇总组合)。

对此的任何建议(也包括用于系统处理此问题的良好工作流程实践)将不胜感激。我一直在使用 "readr" 和基本函数,但每次我 运行 第一次导入时,我都无法解决数据被转换为我需要避免的字符的问题,尽管我也需要保留日期。

是否可以通过一些奇妙的 R 技术解决这个问题,或者我是否需要先对这些许多糟糕的 CSV 文件进行预格式化?

image of what I am dealing with, if it were multiplied by many many times in both directions

如果您的文件的格式都相同,那么您可以 "skip" 行来解决问题。在您的图片示例中,我推断数据看起来像这样,读取一个文件的代码很简单:

dat <- read.csv(text='NAME,% Outstanding,% Outstanding,% Outstanding
,31/12/2018,31/12/2017,31/12/2015
Name01,0.1,0.2,0.3
Name02,0.4,0.5,0.6',
header=TRUE, stringsAsFactors=FALSE, skip=1)
dat
#        X X31.12.2018 X31.12.2017 X31.12.2015
# 1 Name01         0.1         0.2         0.3
# 2 Name02         0.4         0.5         0.6

我选择跳过最前面的那个,因为大多数名字都是多余的,并没有多大帮助。请注意,名称被修改了一点;有关 R 强制执行的列命名规则,请参阅 ?make.names

从这里开始,虽然有点偏好,但我强烈建议从 "wide" 转换为 "tall" 格式。至少有两个原因:(1)列名实际上是数据,因为您可以 want/need 知道从一批数据到另一批数据是“相隔一年”; (2) 许多工具,例如 ggplot2 甚至基本图形(使用它们的 formula 方法)都更喜欢 tall 方法。

我将使用 tidyverse 中的一些内容并解决第一个问题:

colnames(dat)[1] <- "Name"

library(dplyr)
library(tidyr)

首先,关于 wide-to-tall 的注释:

gather(dat, date, pct, -Name)
#     Name        date pct
# 1 Name01 X31.12.2018 0.1
# 2 Name02 X31.12.2018 0.4
# 3 Name01 X31.12.2017 0.2
# 4 Name02 X31.12.2017 0.5
# 5 Name01 X31.12.2015 0.3
# 6 Name02 X31.12.2015 0.6

这会将 "date" 带入 data-realm。事实上,它们经过一点处理(无损)很好,我们可以在下一步中解决这个问题:

gather(dat, date, pct, -Name) %>%
  mutate(
    date = as.Date(date, format = "X%d.%m.%Y")
  )
#     Name       date pct
# 1 Name01 2018-12-31 0.1
# 2 Name02 2018-12-31 0.4
# 3 Name01 2017-12-31 0.2
# 4 Name02 2017-12-31 0.5
# 5 Name01 2015-12-31 0.3
# 6 Name02 2015-12-31 0.6

从这里开始,对多个文件执行此操作应该是:

filelist <- list.files("/path/to/mydir/", pattern="*.csv")
alldata <- lapply(filelist, read.csv, header=TRUE, stringsAsFactors=FALSE, skip=1)
alldata2 <- lapply(alldata, function(dat) {
  gather(dat, date, pct, -Name) %>%
    mutate(date = as.Date(date, format = "X%d.%m.%Y"))
})
combineddata <- do.call(rbind.data.frame, alldata2)

(假设所有文件都具有相同的 2 行 header。)