【问题标题】:R - sqldf() returning dataframe with zero rowsR - sqldf() 返回零行的数据帧
【发布时间】:2018-06-18 02:29:51
【问题描述】:

我正在尝试使用@JD_Long 描述的here 方法从非常大的csv 文件中读取选择数据的有效方法。该方法依赖于同名库中的 sqldf() 函数。我遇到的问题是该函数返回一个空数据框,即具有正确列数及其名称但行数为零的数据框。

一旦数据帧被 sqldf() 读入工作环境,我已经截断了用于处理数据帧的格式化函数。

sum_stats_df <- function(f_name){
  # read in data
  f <- file(f_name, open = "r")
  df <- sqldf("select * from f limit 6", dbname = tempfile(),
              file.format = list(header = T, row.names = F))
  close(f, type='r')
  return(df)

我正在使用的 csv 数据集是我从 ASA 网站 here 下载的著名的交通统计局航班数据。

我尝试了上面链接的 StackOverflow 问题中的示例代码。

bigdf <- data.frame(dim=sample(letters, replace=T, 4e7), fact1=rnorm(4e7), fact2=rnorm(4e7, 20, 50))
write.csv(bigdf, 'bigdf.csv', quote = F)
library(sqldf)
f <- file("bigdf.csv")
bigdf <- sqldf("select * from f", dbname = tempfile(), file.format = list(header = T, row.names = F))

当我打电话给sum_stats_df("bigdf.csv") 时,它工作得很好。我尝试使用 Windows 文件资源管理器中的属性查看模拟文件和航班 csv 文件的属性,但它们看起来相同的信息。唯一的区别是文件大小。航班文件要大得多,但我不明白这有什么关系。

接下来我尝试使用read.csv(..., nrow=20) 加载其中一个航班 csv 文件的 20 行,然后获取生成的数据帧并将其写回 csv 文件。当我在那个新的 csv 测试文件上尝试有问题​​的函数时,它起作用了。

> print(head(sum_stats_df("test.csv")))
    X Year Month DayofMonth DayOfWeek DepTime CRSDepTime ArrTime CRSArrTime UniqueCarrier
1 "1" 1987    10         14         3     741        730     912        849          "PS"
2 "2" 1987    10         15         4     729        730     903        849          "PS"
3 "3" 1987    10         17         6     741        730     918        849          "PS"
4 "4" 1987    10         18         7     729        730     847        849          "PS"
5 "5" 1987    10         19         1     749        730     922        849          "PS"
6 "6" 1987    10         21         3     728        730     848        849          "PS"

但是,使用原始 csv 文件的调用再次返回一个空数据帧。

> print(head(sum_stats_df("2000.csv")))
 [1] Year              Month             DayofMonth        DayOfWeek         DepTime          
 [6] CRSDepTime        ArrTime           CRSArrTime        UniqueCarrier     FlightNum        
[11] TailNum           ActualElapsedTime CRSElapsedTime    AirTime           ArrDelay         
[16] DepDelay          Origin            Dest              Distance          TaxiIn           
[21] TaxiOut           Cancelled         CancellationCode  Diverted          CarrierDelay     
[26] WeatherDelay      NASDelay          SecurityDelay     LateAircraftDelay
<0 rows> (or 0-length row.names)

所以我想知道我从 ASA 下载的 csv 文件与我在本地使用 write.csv() 编写的文件有什么不同? sqldf() 返回空数据框但获取所有列名的其他原因可能是什么?

【问题讨论】:

  • 我看到的一个问题是您使用 LIMIT 而不使用 ORDER BY。这没有任何意义,因为您没有告诉数据库如何您希望限制结果集。 你想要哪 6 条记录?
  • 据我所知,我可能错了,以这种方式使用限制类似于只获取前六行。
  • 但我已经无限制地尝试过了,得到了相同的空数据框。
  • 请阅读this accepted answer,看看你是否可以在你的函数中打开file
  • 添加了 l &lt;- readLines(con=f, n=6); print(l) 并从文件中获取了标题和五个完整的行。我在这里读过很多答案,说 sql 对象在调用后立即被删除,但它没有解释为什么首先将结果分配给df,也没有解释为什么它适用于本地编写的 csv 文件。

标签: r csv sqldf


【解决方案1】:

您可以从引用的网页下载的文件是 bzip 压缩的。直接使用压缩文件时,我可以重现您的问题。一种可能的解决方案是在将文件与sqldf 一起使用之前解压缩文件。这是不幸的,因为其他读取 CSV 文件的工具直接支持 bzip 压缩文件。我不知道如何直接使用sqldf() 执行此操作,但同一包中的read.csv.sql 支持filter 选项,从而可以实现以下功能:

sum_stats_df <- function(f_name){
  read.csv.sql(f_name, sql = "select * from file limit 6", filter = "bunzip2")
}

【讨论】:

  • 感谢您的输入,但我在尝试加载文件之前解压缩了这些文件。不过,我想知道解压缩器是否正在进行某些处理或格式化,这可能是问题的根源。
  • 您在哪个操作系统上使用了哪个工具来解压缩文件?您目前有哪些文件大小?作为比较,2008 年的数据是 109 MB 和 658 MB 没有压缩。
  • 在 Excel 中打开本地创建的 csv 文件和下载并解压缩的文件并没有发现两者有任何区别。但是在 notebook++ 中打开它们会在前者的某些列中显示一些值的引号。考虑到这一点,我尝试使用方法 arg 为每一列定义类。还是不行。
  • 我使用的是 7_zip,解压后的 2008 csv 文件大小为 673MB。
  • 这很奇怪。您可以在打开文件后将print(f) 添加到您的函数中并在其中一个文件上调用该函数时发布结果吗?
【解决方案2】:

SQLite 对行尾字符很挑剔,如果文件来自其他地方,这些字符可能与操作系统上的默认字符不同。

在 Windows 和 Linux Ubuntu 上,假设您已经解压缩它,这对我有用:

read.csv.sql("1987.csv", "select * from file limit 3", eol = "\n")

或者在 Windows 上使用原始 bz2 文件并假设 7z 可执行文件在您的路径上:

read.csv.sql("1987.csv", "select * from file limit 3", eol = "\n",
    filter = "7z x -so 1987.csv.bz2 2>NUL")

在 Linux 上,我们可以使用 bzip2:

read.csv.sql("1987.csv", "select * from file limit 3", eol = "\n",
    filter = "bzip2 -cd 1987.csv.bz2")

sqldf github page 上的常见问题解答 16 有一个与此非常相似的示例。

【讨论】:

    猜你喜欢
    • 2018-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-29
    • 2015-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多