【问题标题】:R: Loop through a list of csv files to alter date format and create XTS objectsR:循环遍历 csv 文件列表以更改日期格式并创建 XTS 对象
【发布时间】:2016-07-21 17:33:58
【问题描述】:

我正在尝试导入 csv 文件并最终将它们转换为 R 中的 XTS 对象。

每个单独的 csv 格式为:

Date       Open    High    Low     Close    Volume
18-Jun-99   2.35    2.35    2.35    2.35    34000
21-Jun-99   2.35    2.35    2.35    2.35    57317
22-Jun-99   2.35    2.35    2.35    2.35    7000

这里的问题是日期,但是 lubridate 中的一个函数可以轻松地转换它。对于单个 csv,我的流程如下:

require(xts)
CAR.csv <- read.csv("CAR.csv", header = TRUE)
require(lubridate)
CAR.csv$Date <- dmy(CAR.csv$Date)
CAR.csv <- read.zoo(CAR.csv)
CAR.csv <- as.xts(CAR.csv)

但是,我需要为数百个文件执行此操作,因此我希望能够遍历所有文件。我现在被困在这一点上:

setwd("C:/Users/Administrator/Desktop/data")
library(xts)
temp = list.files(pattern="*.csv")
for (i in 1:length(temp)) assign(temp[i], read.csv(temp[i], header = TRUE))

我真的不知道如何将 dmy 函数仅应用于循环中的日期列,我希望任何可以为我指明正确方向的帮助。

具有正确日期格式的 csv 文件循环的先前版本是这样的:

setwd("C:/Users/Administrator/Desktop/data")
library(xts)
temp = list.files(pattern="*.csv")
toDate <- function(x) as.Date(x, origin = "2005-01-01")
for (i in 1:length(temp)) assign(temp[i], as.xts(read.zoo((temp[i]), header = TRUE, sep = ",", FUN = toDate)))

就完全可重现的示例而言,如果需要,这里是 csv 的 sample folder,但我怀疑这对于大多数有能力的 R 用户来说是直截了当的。

我当然会喜欢一些建议。

非常感谢

【问题讨论】:

    标签: r xts


    【解决方案1】:
    setwd("C:/Users/Administrator/Desktop/data")
    library(xts)
    library(lubridate)
    
    load_file <- function(file_name) {
      csv_file <- read.csv(file_name, header = TRUE)
      csv_file$Date.Time <- dmy(csv_file$Date.Time)
      csv_file <- read.zoo(csv_file)
      csv_file <- as.xts(csv_file)
    
      csv_file
    }
    
    list_of_files = list.files(pattern="*.csv")
    
    data <- lapply(X = list_of_files, FUN = load_file)
    

    代码通过定义一个函数来工作,当给定工作目录中的文件名时,该函数读取它,然后对该文件执行所需的转换。请注意,在您的示例数据中,日期列称为Date.Time,因此我更改了代码以反映这一点。

    我没有使用循环,而是使用基本apply(...) 函数将该函数应用于文件名列表中的每个单独的文件名。此操作的输出是一个列表,其中包含您要转换的数据。要访问每个数据对象,请使用data[[1]] 等。

    【讨论】:

    • 您好@Alex,感谢您的帮助。是否认为使用函数和 lapply 将允许将 csv 文件分配给全局环境中的单个 XTS 对象,而不是单个对象?非常感谢。
    • 我的荣幸。我上面代码中data 列表中的每个元素都是全局环境中的一个单独的XTS 对象。您可以命名每个元素 - 例如names(data) &lt;- list_of_files 这样您就可以引用它们,例如 data['CDM.csv']data$CDM.csv,或者您可以将它们重新分配给其他名称 - 例如first_xts_objext &lt;- data[[1]]。希望这会有所帮助。
    • 另外,如果您想将每个单独的 XTS 对象分配给全局环境中的不同对象,您可以将 load_file 函数的最后一行更改为 assign(file_name, csv_file, envir = .GlobalEnv)。这应该会在全局环境中为您留下诸如CDM.csv 等名称的对象。
    【解决方案2】:

    只需将您的 for 循环更改为对单个文件执行的操作即可:

    for (i in 1:length(temp)){
      assign("new.tmp", read.csv(temp[i], header = TRUE))
      new.tmp$Date <- dmy(new.tmp$Date)
      new.tmp <- read.zoo(new.tmp)
      assign(temp[i],as.xts(new.tmp))
    }
    

    这可能会花费一点时间,因为您会在每次循环迭代中多次复制整个对象,但我认为这是最简单的解决方案。

    【讨论】:

    • 感谢@snaut 这个方法的帮助。我喜欢这种方法。是否可以调整您的循环,使每个单独的 csv 在全局环境中成为单独的 XTS 对象?非常感谢
    • 在这个循环中应该是这样,如果在全局环境中运行,assign(temp[i], value) 会为名为@9​​87654323@ 的变量赋值。
    【解决方案3】:

    一般来说,我更喜欢在循环之前初始化一个列表,读取并处理该文件,然后将它们存储回列表中。

    这种方法的主要优点是:

    1. 保持环境清洁
    2. 能够使用lapply 对所有加载的文件进行相同的处理
    3. 能够通过简单地按文件名或索引对其进行索引来提取/处理单个文件

    代码示例:

    paths.allFiles = list.files(pattern="*.csv") # Equivalent to "temp"
    processedCSVs = list()
    
    for(path.oneFile in paths.allFiles){ # hint: you can access the file names directly without indexing
      csv =  as.xts(read.zoo(path.oneFile, header = TRUE, sep = ",", FUN = toDate))
      processedCSVs[path.oneFile] = csv
    }
    
    lapply(processedCSVs, nrow) # Returns all the nrows of all files
    nrow(processedCSVs[[1]]) # Returns the nrows of the indexed file only 
    

    【讨论】:

      猜你喜欢
      • 2014-08-17
      • 1970-01-01
      • 2016-11-22
      • 2018-10-01
      • 2018-06-08
      • 1970-01-01
      • 2021-03-24
      • 2019-09-29
      • 2017-10-02
      相关资源
      最近更新 更多