如何在python中处理大型csv文件?
我有一个包含40k行数据的CSV文件 我的每个函数打开csv文件并使用它,然后关闭它。 有没有一种方法,我可以打开一次文件,然后关闭它,我可以随时使用它?我试图将每个字段放在一个单独的列表中,并在每次调用它或在字典中使用它,但这两种方法在1k行内都很有效。如果超过1k行,则需要较长的时间来处理它,我找到了一种通过过滤它们来加快速度的方法,但不确定如何应用它 我的代码样本如何在python中处理大型csv文件?,python,function,csv,Python,Function,Csv,我有一个包含40k行数据的CSV文件 我的每个函数打开csv文件并使用它,然后关闭它。 有没有一种方法,我可以打开一次文件,然后关闭它,我可以随时使用它?我试图将每个字段放在一个单独的列表中,并在每次调用它或在字典中使用它,但这两种方法在1k行内都很有效。如果超过1k行,则需要较长的时间来处理它,我找到了一种通过过滤它们来加快速度的方法,但不确定如何应用它 我的代码样本 files=open("myfile.csv","r") def spec_total(): total = 0.
files=open("myfile.csv","r")
def spec_total():
total = 0.0
files.readline() # skip first row
for line in files:
field=line.strip().split(",") #make Into fields
tall=float(field[0])
if tall >= 9.956:
total +=tall
print("The sum is: %0.5f" % (total))
spec_total()
files.close()
其他功能
files=open("3124749c.csv","r")
def code():
match= 0
files.readline() # skip first row
for row in files:
field=row.strip().split(",") #make Into fields
code=(field[4])
import re
if re.search(r'\[[A-Za-z][0-9]+\][0-9]+[A-Za-z]{2}[0-9]+#[0-9]+', code) is None:
match += 1
print("The answer that do not match code is :",match)
code()
files.close()
每次打开csv文件时都会打开更多的函数,并将它们拆分为字段,以便识别我所指的字段。如果我理解正确,请尝试:
import csv
total = 0.0
for row in csv.reader(open("myfile.csv")):
tall = float(row[0])
if tall >= 9.956:
total += tall
print("The sum is: %0.5f" % total)
更复杂的版本-创建用于处理每行的计算类
class Calc(object):
def process(self,row):
pass
def value(self):
pass
class SumColumn(Calc):
def __init__(self, column=0,tall=9.956):
self.column = column
self.total = 0
def process(self, row):
tall = float(row[0])
if tall >= self.tall:
self.total += tall
def value(self):
return self.total
class ColumnAdder(Calc):
def __init__(self, col1, col2):
self.total = 0
self.col1 = col1
self.col2 = col2
def process(self, row):
self.total += (row[self.col1] + row[self.col2])
def value(self):
return self.total
class ColumnMatcher(Calc):
def __init__(self, col=4):
self.matches = 0
def process(self, row):
code = row[4]
import re
if re.search(r'\[[A-Za-z][0-9]+\][0-9]+[A-Za-z]{2}[0-9]+#[0-9]+', code) is None:
self.match += 1
def value(self):
return self.matches
import csv
col0_sum = SumColumn()
col3_sum = SumColumn(3, 2.45)
col5_6_add = ColumnAdder(5,6)
col4_matches = ColumnMatcher()
for row in csv.reader(open("myfile.csv")):
col0_sum.process(row)
col3_sum.process(row)
col5_6_add.process(row)
col4_matches.process(row)
print col0_sum.value()
print col3_sum.value()
print col5_6_add.value()
print col4_matches.value()
这段代码被输入到SO中,这是一件乏味的事情——在语法等方面非常简单
仅用于说明目的-不要过于字面化。如果我理解正确,请尝试:
import csv
total = 0.0
for row in csv.reader(open("myfile.csv")):
tall = float(row[0])
if tall >= 9.956:
total += tall
print("The sum is: %0.5f" % total)
更复杂的版本-创建用于处理每行的计算类
class Calc(object):
def process(self,row):
pass
def value(self):
pass
class SumColumn(Calc):
def __init__(self, column=0,tall=9.956):
self.column = column
self.total = 0
def process(self, row):
tall = float(row[0])
if tall >= self.tall:
self.total += tall
def value(self):
return self.total
class ColumnAdder(Calc):
def __init__(self, col1, col2):
self.total = 0
self.col1 = col1
self.col2 = col2
def process(self, row):
self.total += (row[self.col1] + row[self.col2])
def value(self):
return self.total
class ColumnMatcher(Calc):
def __init__(self, col=4):
self.matches = 0
def process(self, row):
code = row[4]
import re
if re.search(r'\[[A-Za-z][0-9]+\][0-9]+[A-Za-z]{2}[0-9]+#[0-9]+', code) is None:
self.match += 1
def value(self):
return self.matches
import csv
col0_sum = SumColumn()
col3_sum = SumColumn(3, 2.45)
col5_6_add = ColumnAdder(5,6)
col4_matches = ColumnMatcher()
for row in csv.reader(open("myfile.csv")):
col0_sum.process(row)
col3_sum.process(row)
col5_6_add.process(row)
col4_matches.process(row)
print col0_sum.value()
print col3_sum.value()
print col5_6_add.value()
print col4_matches.value()
这段代码被输入到SO中,这是一件乏味的事情——在语法等方面非常简单
仅供说明之用-不要太字面化。Python中的All是object:这也意味着函数。
因此,没有必要像sotapme那样定义特殊的类来制作函数作为这些类的实例,因为我们定义的每个函数都已经是“类的实例”意义上的对象 现在,如果有人需要创建多个相同类型的函数,例如,每个函数都添加一个精确CSV文件列的所有值,那么通过重复过程创建这些函数是很有趣的。
此时,提出了一个问题:使用函数工厂还是类 就个人而言,我更喜欢函数工厂的方式,因为它不太冗长。
我还发现在塞兰的回答中,它也更快 在下面的代码中,我使用globals()技巧为通过函数工厂创建的每个函数指定一个特定的名称。有人会说这很糟糕,但我不知道为什么。如果有其他方法可以做到这一点,我会很高兴地学习它 在代码中,有3个函数是由函数工厂构建的,其中一个是由普通法线定义(op3)定义的 Python太棒了
import csv
import re
# To create a CSV file
with open('Data.csv','wb') as csvhandle:
hw = csv.writer(csvhandle)
hw.writerows( ((2,10,'%%',3000,'-statusOK-'),
(5,3,'##',500,'-modo OOOOKKK-'),
(1,60,'**',700,'-- anarada-')) )
del hw
# To visualize the content of the CSV file
with open(r'Data.csv','rb') as f:
print "The CSV file at start :\n "+\
'\n '.join(map(repr,csv.reader(f)))
def run_funcs_on_CSVfile(FUNCS,CSV):
with open(CSV,'rb') as csvhandle:
for f in FUNCS:
# this is necessary for functions not created via
# via a function factory but via plain definition
# that defines only the attribute col of the function
if 'field' not in f.__dict__:
f.field = f.col - 1
# columns are numbered 1,2,3,4,...
# fields are numbered 0,1,2,3,...
for row in csv.reader(csvhandle):
for f in FUNCS:
f(row[f.field])
def SumColumn(name,col,start=0):
def g(s):
g.kept += int(s)
g.kept = start
g.field = col -1
g.func_name = name
globals()[name] = g
def MultColumn(name,col,start=1):
def g(s):
g.kept *= int(s)
g.kept = start
g.field = col - 1
g.func_name = name
globals()[name] = g
def ColumnMatcher(name,col,pat,start = 0):
RE = re.compile(pat)
def g(s,regx = RE):
if regx.search(s):
g.kept += 1
g.kept = start
g.field = col - 1
g.func_name = name
globals()[name] = g
SumColumn('op1',1)
MultColumn('op2',2)
ColumnMatcher('op4',5,'O+K')
def op3(s):
s = int(s)
if s%2:
op3.kept += (2*s)
else:
op3.kept += s
op3.kept = 0
op3.col = 4
print '\nbefore:\n ' +\
'\n '.join('%s.kept == %d'
% (f.func_name, f.kept)
for f in (op1,op2,op3,op4) )
# The treatment is done here
run_funcs_on_CSVfile((op2,op3,op4,op1),r'Data.csv')
# note that the order of the functions in the tuple
# passed as argument can be any either one or another
print '\nafter:\n ' +\
'\n '.join('%s(column %d) in %s.kept == %d'
% (f.func_name, f.field+1, f.func_name, f.kept)
for f in (op1,op2,op3,op4) )
。
结果
Python中的All是object:也就是说函数。
因此,没有必要像sotapme那样定义特殊的类来制作函数作为这些类的实例,因为我们定义的每个函数都已经是“类的实例”意义上的对象 现在,如果有人需要创建多个相同类型的函数,例如,每个函数都添加一个精确CSV文件列的所有值,那么通过重复过程创建这些函数是很有趣的。
此时,提出了一个问题:使用函数工厂还是类 就个人而言,我更喜欢函数工厂的方式,因为它不太冗长。
我还发现在塞兰的回答中,它也更快 在下面的代码中,我使用globals()技巧为通过函数工厂创建的每个函数指定一个特定的名称。有人会说这很糟糕,但我不知道为什么。如果有其他方法可以做到这一点,我会很高兴地学习它 在代码中,有3个函数是由函数工厂构建的,其中一个是由普通法线定义(op3)定义的 Python太棒了
import csv
import re
# To create a CSV file
with open('Data.csv','wb') as csvhandle:
hw = csv.writer(csvhandle)
hw.writerows( ((2,10,'%%',3000,'-statusOK-'),
(5,3,'##',500,'-modo OOOOKKK-'),
(1,60,'**',700,'-- anarada-')) )
del hw
# To visualize the content of the CSV file
with open(r'Data.csv','rb') as f:
print "The CSV file at start :\n "+\
'\n '.join(map(repr,csv.reader(f)))
def run_funcs_on_CSVfile(FUNCS,CSV):
with open(CSV,'rb') as csvhandle:
for f in FUNCS:
# this is necessary for functions not created via
# via a function factory but via plain definition
# that defines only the attribute col of the function
if 'field' not in f.__dict__:
f.field = f.col - 1
# columns are numbered 1,2,3,4,...
# fields are numbered 0,1,2,3,...
for row in csv.reader(csvhandle):
for f in FUNCS:
f(row[f.field])
def SumColumn(name,col,start=0):
def g(s):
g.kept += int(s)
g.kept = start
g.field = col -1
g.func_name = name
globals()[name] = g
def MultColumn(name,col,start=1):
def g(s):
g.kept *= int(s)
g.kept = start
g.field = col - 1
g.func_name = name
globals()[name] = g
def ColumnMatcher(name,col,pat,start = 0):
RE = re.compile(pat)
def g(s,regx = RE):
if regx.search(s):
g.kept += 1
g.kept = start
g.field = col - 1
g.func_name = name
globals()[name] = g
SumColumn('op1',1)
MultColumn('op2',2)
ColumnMatcher('op4',5,'O+K')
def op3(s):
s = int(s)
if s%2:
op3.kept += (2*s)
else:
op3.kept += s
op3.kept = 0
op3.col = 4
print '\nbefore:\n ' +\
'\n '.join('%s.kept == %d'
% (f.func_name, f.kept)
for f in (op1,op2,op3,op4) )
# The treatment is done here
run_funcs_on_CSVfile((op2,op3,op4,op1),r'Data.csv')
# note that the order of the functions in the tuple
# passed as argument can be any either one or another
print '\nafter:\n ' +\
'\n '.join('%s(column %d) in %s.kept == %d'
% (f.func_name, f.field+1, f.func_name, f.kept)
for f in (op1,op2,op3,op4) )
。
结果
“必须”吗?为什么?用“我想实现XY,到目前为止我已经做到了”来重新表述你的问题,你会更幸运地使用标准库
csv
,调用total(字段[0])
而不让它访问全局数据似乎是有意义的。@Dragets:我根本不清楚你想实现什么。请你重新措辞好吗?我希望我把问题写得更具体一些。很抱歉没有理解。我怀疑如果你在一次将整个文件加载到内存中时遇到性能问题,没有比每次需要使用时重新加载文件更快的方法了。行分割可能比你正在做的其他事情要快!“必须”吗?为什么?用“我想实现XY,到目前为止我已经做到了”来重新表述你的问题,你会更幸运地使用标准库csv
,调用total(字段[0])
而不让它访问全局数据似乎是有意义的。@Dragets:我根本不清楚你想实现什么。请你重新措辞好吗?我希望我把问题写得更具体一些。很抱歉没有理解。我怀疑如果你在一次将整个文件加载到内存中时遇到性能问题,没有比每次需要使用时重新加载文件更快的方法了。行分割可能比你正在做的其他事情要快!使用此代码仍然需要每个函数打开csv文件并拆分它们。。。我当时的想法是,我编写了一个函数来完成这项工作,并以某种方式将它们与我的所有其他函数关联起来,因为我的所有其他函数都与csv文件中的数据相关。我不确定你的问题,也许你可以编写一些代码来演示它。如果有n
函数实际上是基于每行中的列进行计算,那么最好为每个计算创建类。我将编辑以显示我的意思。我重新编写了更具体的问题,并添加了一些示例您的匹配部分可以很容易地添加为一个类,该类实现了我认为我已经说明的功能。这是另一个只依赖于文件中一行的计算,它可以以与ColumnAdder类似的方式累积结果