【问题标题】:Read list of file names from web into R从网络读取文件名列表到 R
【发布时间】:2013-04-11 16:49:37
【问题描述】:

我正在尝试从网站将大量 csv 文件读入 R。 Thra 是多年的每日(仅限工作日)文件。所有文件都具有相同的数据结构。我可以使用以下逻辑成功读取 一个 文件:

# enter user credentials
user     <- "JohnDoe"
password <- "SecretPassword"
credentials <- paste(user,":",password,"@",sep="")
web.site <- "downloads.theice.com/Settlement_Reports_CSV/Power/"

# construct path to data
path <- paste("https://", credentials, web.site, sep="")

# read data for 4/10/2013
file  <- "icecleared_power_2013_04_10"
fname <- paste(path,file,".dat",sep="")
df <- read.csv(fname,header=TRUE, sep="|",as.is=TRUE)

但是,我正在寻找有关如何一次读取目录中所有文件的提示。我想我可以生成一系列日期,并在循环中构造上面的文件名并使用 rbind 附加每个文件,但这似乎很麻烦。此外,在没有文件的周末和节假日尝试阅读时也会出现问题。

下图显示了文件列表在网络浏览器中的样子:

... ... ...

有没有办法扫描路径(从上面)以获取目录中首先满足特定条件的所有文件名的列表(即以“icecleared_power_”开头,因为该位置也有一些文件有一个我不想读入的不同起始名称)然后在该列表中循环 read.csv 并使用 rbind 追加?

任何指导将不胜感激?

【问题讨论】:

  • 浏览器中的实际网页是什么样的?是否有某种索引页面,您可以轻松地筛选/网络抓取以获取列表相关文件以构建您的下载命令?
  • Ananda:请查看带有网络浏览器屏幕截图的编辑。

标签: r dataframe


【解决方案1】:

我会首先尝试抓取相关数据文件的链接,并使用生成的信息来构建包含用户登录等的完整下载路径。正如其他人建议的那样,lapply 可以方便批量下载。

这是一种提取 URL 的简单方法。显然,修改示例以适合您的实际情况。

在这里,我们将使用 XML 包来识别 Amelia 包 (http://cran.r-project.org/src/contrib/Archive/Amelia/) 的 CRAN 档案中可用的所有链接。

> library(XML)
> url <- "http://cran.r-project.org/src/contrib/Archive/Amelia/"
> doc <- htmlParse(url)
> links <- xpathSApply(doc, "//a/@href")
> free(doc)
> links
                   href                    href                    href 
             "?C=N;O=D"              "?C=M;O=A"              "?C=S;O=A" 
                   href                    href                    href 
             "?C=D;O=A" "/src/contrib/Archive/"  "Amelia_1.1-23.tar.gz" 
                   href                    href                    href 
 "Amelia_1.1-29.tar.gz"  "Amelia_1.1-30.tar.gz"  "Amelia_1.1-32.tar.gz" 
                   href                    href                    href 
 "Amelia_1.1-33.tar.gz"   "Amelia_1.2-0.tar.gz"   "Amelia_1.2-1.tar.gz" 
                   href                    href                    href 
  "Amelia_1.2-2.tar.gz"   "Amelia_1.2-9.tar.gz"  "Amelia_1.2-12.tar.gz" 
                   href                    href                    href 
 "Amelia_1.2-13.tar.gz"  "Amelia_1.2-14.tar.gz"  "Amelia_1.2-15.tar.gz" 
                   href                    href                    href 
 "Amelia_1.2-16.tar.gz"  "Amelia_1.2-17.tar.gz"  "Amelia_1.2-18.tar.gz" 
                   href                    href                    href 
  "Amelia_1.5-4.tar.gz"   "Amelia_1.5-5.tar.gz"   "Amelia_1.6.1.tar.gz" 
                   href                    href                    href 
  "Amelia_1.6.3.tar.gz"   "Amelia_1.6.4.tar.gz"     "Amelia_1.7.tar.gz" 

为了演示,假设最终我们只需要 1.2 版本的包的链接。

> wanted <- links[grepl("Amelia_1\\.2.*", links)]
> wanted
                  href                   href                   href 
 "Amelia_1.2-0.tar.gz"  "Amelia_1.2-1.tar.gz"  "Amelia_1.2-2.tar.gz" 
                  href                   href                   href 
 "Amelia_1.2-9.tar.gz" "Amelia_1.2-12.tar.gz" "Amelia_1.2-13.tar.gz" 
                  href                   href                   href 
"Amelia_1.2-14.tar.gz" "Amelia_1.2-15.tar.gz" "Amelia_1.2-16.tar.gz" 
                  href                   href 
"Amelia_1.2-17.tar.gz" "Amelia_1.2-18.tar.gz" 

您现在可以按如下方式使用该向量:

wanted <- links[grepl("Amelia_1\\.2.*", links)]
GetMe <- paste(url, wanted, sep = "")
lapply(seq_along(GetMe), 
       function(x) download.file(GetMe[x], wanted[x], mode = "wb"))

更新(澄清您在 cmets 中的问题)

上面示例中的最后一步下载指定文件到您当前的工作目录(使用getwd() 来验证它的位置)。相反,如果您确定 read.csv 对数据有效,您也可以尝试修改匿名函数以直接读取文件:

lapply(seq_along(GetMe), 
       function(x) read.csv(GetMe[x], header = TRUE, sep = "|", as.is = TRUE))

但是,我认为 更安全 的方法可能是首先将所有文件下载到单个目录中,然后使用 read.delimread.csv 或任何可以读取数据的方法,类似按照@Andreas 的建议。我说 更安全 是因为它在文件未完全下载等情况下为您提供了更大的灵活性。在这种情况下,您无需重新下载所有内容,只需下载未完全下载的文件即可。

【讨论】:

  • 谢谢,一旦我让 htmlParse 工作,它看起来会很好用。出于某种原因,我的 URL 出现以下错误:“错误:XML 内容似乎不是 XML,也不是识别文件名”有什么想法吗?
  • 我似乎已经通过修改 htmlParse 解决了“错误:XML ...”问题,如下所示:doc
  • @MikeTP,lapply 步骤应根据您的需要进行修改。在此示例中,由于文件是二进制文件,因此我只是将它们下载到我的工作目录中。如果您确定可以直接从在线资源中阅读它们,那么您可以将download.file(...) 替换为您的read.csv(...) 命令。这会将所有文件读入list,然后从那里,您可以将它们作为单独的data.frames 保存,或者,如果结构都相同,您可以将rbind 它们放入一个data.frame。希望有帮助!
  • 谢谢!我必须先使用库httr 才能访问数据库,例如library(httr),然后是GET(url, authenticate("email@email.com", "password"), write_disk("test.html")),然后是doc &lt;- htmlParse("test.html"),等等。
【解决方案2】:

@MikeTP,如果所有报告都以“icecleared_power_”开头且日期为营业日期,则“timeDate”包提供了一种创建营业日期向量的简单方法,如下所示:

require(timeDate)
tSeq <- timeSequence("2012-01-01","2012-12-31") # vector of days
tBiz <- tSeq[isBizday(tSeq)] # vector of business days

paste0("icecleared_power_",as.character.Date(tBiz))

为您提供连接的文件名。

如果网站在文件命名方面遵循不同的逻辑,我们需要更多信息,正如 Ananda Mahto 所观察到的那样。

请记住,当您使用 timeDate 创建日期向量时,您可以比我的简单示例更复杂。您可以考虑假期时间表、证券交易所日期等。

【讨论】:

  • 谢谢。我认为使用 Ananda 的建议对我来说更有意义,但我会看看 timeDate,因为它看起来对其他应用程序很有用。我非常感谢您的回复。再次感谢。
【解决方案3】:

您可以尝试使用命令“download.file”。

### set up the path and destination
path <- "url where file is located"
dest <- "where on your hard disk you want the file saved"

### Ask R to try really hard to download your ".csv"
try(download.file(path, dest))

解决这个问题的诀窍是弄清楚文件之间的“url”或“path”如何系统地变化。很多时候,网页的构建使得“url”是系统的。在这种情况下,您可能会创建一个 url 的向量或数据框,以便在 apply 函数内部进行迭代。

所有这些都可以夹在“lapply”中。 “数据”对象就是我们迭代的任何东西。它可以是 URL 的向量或年份和月份观察的数据框,然后可用于在“lapply”函数中创建 URL。

### "dl" will apply a function to every element in our vector "data"
  # It will also help keep track of files which have no download data
dl <- lapply(data, function(x) {
        path <- 'url'
        dest <- './data_intermediate/...'
        try(download.file(path, dest))
      })

### Assign element names to your list "dl"
names(dl) <- unique(data$name)
index     <- sapply(dl, is.null)

### Figure out which downloads returned nothing
no.download <- names(dl)[index]

然后您可以使用“list.files()”将所有数据合并在一起,假设它们属于一个 data.frame

### Create a list of files you want to merge together
files <- list.files()

### Create a list of data.frames by reading each file into memory
data  <- lapply(files, read.csv)

### Stack data together
data <- do.call(rbind, data)

有时,您会注意到下载后文件已损坏。在这种情况下,请注意 download.file() 命令中包含的选项“mode”。如果文件以二进制格式存储,则可以设置 mode = "w" 或 mode = "wb"。

【讨论】:

  • 感谢您的帮助。 lapply 函数中的“数据”从何而来?
  • "data" 只是您正在迭代的对象。例如,它可以是指向您要下载的文件的 URL 向量。或者,它可能是一个年份和月份观察数据框,可以帮助我们在每个循环中创建一个 URL。
【解决方案4】:

另一种解决方案

for( i in seq_along(stations)) {
     URL<-""
      files<-rvest::read_html(URL) %>% html_nodes("a") %>% html_text(trim = T) 
      files<-grep(stations[i],files ,ignore.case = TRUE, value = TRUE )   
      destfile<- paste0("C:/Users/...",files)
      download.file(URL,destfile, mode="wb") 
   }    
    

【讨论】:

  • 可以通过向 OP 解释如何获取“站”列表和/或 URL 值来改进此答案,因为这是原始问题的一部分。
猜你喜欢
  • 2014-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多