使用Python解析12GB CSV
我有一个12 GB的CSV文件。我希望从这些数据中只提取一些列,然后编写一个新的CSV,希望可以加载到R中进行分析 问题是,在写入新的CSV文件之前,试图一次加载整个列表时,我遇到了内存错误。如何逐行解析数据,然后创建CSV输出 以下是我到目前为止的情况:使用Python解析12GB CSV,python,r,csv,bigdata,Python,R,Csv,Bigdata,我有一个12 GB的CSV文件。我希望从这些数据中只提取一些列,然后编写一个新的CSV,希望可以加载到R中进行分析 问题是,在写入新的CSV文件之前,试图一次加载整个列表时,我遇到了内存错误。如何逐行解析数据,然后创建CSV输出 以下是我到目前为止的情况: import pandas colnames = ['contributor name', 'recipient name', 'recipient party', 'contributor cfscore', 'candidate cfs
import pandas
colnames = ['contributor name', 'recipient name', 'recipient party', 'contributor cfscore', 'candidate cfscore', 'amount']
DATA = pandas.read_csv('pathname\filename.csv', names=colnames)
DATA.to_csv(''pathname\filename.csv', cols = colnames)
试试这个:
file = open("csv.csv", "r")
for line in file:
print(line)
它不会将整个文件加载到内存中,而是逐行解析。在R中,您可以使用流行的
您可以使用drop=参数指定不被读取的列-没有为它们分配内存,并且它们根本不被读取。或者,如果方便的话,选择要保留的列。fread可以非常非常快速地读取csv文件
如果您要处理这么多的数据,您可能需要熟悉data.table包
或者,从中读取.csv.sql表示它将
将文件读入R,并使用sql语句对其进行筛选。R只处理过滤后的部分,以便容纳比R可以处理的文件大的文件
下面是一个例子:
write.csv(iris, "iris.csv", quote = FALSE, row.names = FALSE)
iris2 <- read.csv.sql("iris.csv",
sql="select * from file where Species = 'setosa' ")
您可以使用csv模块逐行处理文件。类似的方法可能会奏效:
import csv
infname = "csv.csv"
outfname = "csv_stripped.csv"
cols = ["col1", "col2", "col3"]
with open(infname) as inf, open(outfname, 'w+') as outf:
reader = csv.DictReader(inf)
writer = csv.DictWriter(outf, cols, extrasaction='ignore')
writer.writeheader()
for line in reader:
writer.writerow(line)
供参考:
首先将所有数据读入内存不是一个好主意 有两种方法可以处理如此大的数据文件 对每一行进行流式处理,选择相关信息并忽略其余部分,直到EOF。请参阅xml解析器 对每一行进行流式处理,并将整个数据写入更好的格式,以便轻松访问相关信息。例如,pytables 如果您有一个函数filter_row,当您想要保留该行时,该函数返回True,则可以使用:
with open('input.csv') as inp:
with open('output.csv', 'w') as outp:
for line in inp:
if filter_row(line):
outp.write(line)
您不需要python或任何额外的R包来完成这项工作。在R中输入数据时,可以使用colClasses参数来仅读取某些列。将colClasses值设为NULL,以防止在输入期间加载该列 例如,对于包含3列的文件myfile.csv,如果第一列应视为字符,第三列应视为整数,第二列应忽略:
read.csv("myfile.csv", colClasses=c("character", "NULL", "integer"))
但是,此方法要求您为文件中的每一列指定类
如果您有许多行,那么您可能也值得阅读关于内存使用的建议。您可以使用R和JDBC实现这一点。让我们创建一个示例csv文件
write.table(x=mtcars, file="mtcars.csv", sep=",", row.names=F, col.names=T) # create example csv file
从以下链接下载并保存CSV JDBC驱动程序:然后设置驱动程序
> library(RJDBC)
> path.to.jdbc.driver <- "jdbc//csvjdbc-1.0-18.jar"
> drv <- JDBC("org.relique.jdbc.csv.CsvDriver", path.to.jdbc.driver)
> conn <- dbConnect(drv, sprintf("jdbc:relique:csv:%s", getwd())) # replace getwd() with location of csv file
你看过csvkit吗?我不知道它在效率和速度方面是怎样的。顺便说一句,你从哪里得到那个文件的?试试这个。该工具集有一系列广泛的数据操作例程,这些例程应该允许您对数据进行切片、切分,甚至进行一些初步聚合,以使数据更易于管理。此外,如果您可以将数据放入一个简单的数据库中,dplyr可能是处理数据的最佳选择,因为它很可能不会占用您所有的内存。因为文件中的行应该一次读取一行,而不在内存中全部加载。当您读取行时,会加载文件。对文件中的行进行迭代:printline不会将整个文件加载到内存中,事实上可以处理无限流。@AaronHall修复了帖子,没有意识到因为行中的行不会将整个文件加载到内存中。@M4rtini更正了我的答案。谢谢谢谢你。我试着使用你在发布之前描述过的fread,但是大约25分钟后,会得到一个关于分隔符的错误…@user3342483可能会咬人如果可以使用verbose=TRUE再次运行它并将输出发送到datatable帮助列表,那就太好了。或者,如果该文件在线可用,您可以提供一个链接,这将有助于调试。该文件在此链接可用,请注意,它是2GB:R给我的错误是:fread~/bonicasideal/contribDB_2012.csv中的错误,verbose=T,select=ccontributor name,:Expected sep',但在读取数据时,第35265行的字段20结束:2012,e:ind:2012:32748445,15,752011-09-30418539734,arbitter,daniel s s,arbitter,daniel s,s,,,daniel s s,I,M,14871 lakewood dr,plymouth,MI,481702694,core veh经理dyn@user3342483谢谢你的文件。我下载并检查了它。第35265行在字段20中有一个\n。我使用了:head-n35267contribdb_2012.csv | tail-n4来查看这条线。fread尚未处理嵌入式\n。我来看看…@user3342483嵌入的问题是。我已经在您的12GB文件上进行了测试,可以从中选择=列。有几个字段有一系列反斜杠,这些反斜杠也是固定的,并添加了测试。现在应该可以工作了。@user3342483您可能在某个地方出错了,可能是列名或分隔符?。我刚刚做了一个简单的测试,它对我很有用。对不起,我无意中删除了我最后的评论。我认为我的名字中的空格会让事情变得很糟……从技术上讲,这可能是个错误
当然可以,但是在12GB文件上读取.csv的性能肯定会是一个问题。的确,这比读取没有空值的整个文件要快,但仍然相当慢。
> dbGetQuery(conn, "select mpg, cyl, gear from mtcars where gear = '5'")
mpg cyl gear
1 26 4 5
2 30.4 4 5
3 15.8 8 5
4 19.7 6 5
5 15 8 5