R - sqldf() 返回零行的数据帧



我正在尝试一种有效的方法,使用 @JD_Long 这里描述的方法从非常大的 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网站下载了这些数据。

我尝试了上面链接的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()返回空数据帧但获取所有列名的其他原因可能是什么?

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页面上的FAQ 16有一个与此非常相似的示例。

您可以从引用的网页下载的文件是 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")
}

最新更新