将具有时间序列的大型混合 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。)
我是 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。)