我正在尝试使用@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文件的二十行,然后获取结果数据帧并将其写回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()
返回空数据帧但获取所有列名称的其他原因可能是什么?
答案 0 :(得分:0)
您可以从引用的网页下载的文件是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")
}
答案 1 :(得分:0)
SQLite对行尾字符很挑剔,如果文件来自其他地方,这些字符可能与操作系统上的默认字符不同。
在Windows和Linux Ubuntu上,假设您已经解压缩它,这对我有用:
NewLine
或在Windows上使用原始bz2文件进行此变体,并假设7z可执行文件位于您的路径上:
read.csv.sql("1987.csv", "select * from file limit 3", eol = "\n")
在Linux上我们可以使用bzip2代替:
read.csv.sql("1987.csv", "select * from file limit 3", eol = "\n",
filter = "7z x -so 1987.csv.bz2 2>NUL")
sqldf github page上的常见问题解答16有一个与此非常相似的示例。