在大型表上操作:使用python一次操作一组行
我有一个巨大的表文件,如下所示。为了处理单个产品(名称),我尝试使用pandas groupby,但它似乎将整个表(~10G)放在内存中,这是我无法负担的在大型表上操作:使用python一次操作一组行,python,Python,我有一个巨大的表文件,如下所示。为了处理单个产品(名称),我尝试使用pandas groupby,但它似乎将整个表(~10G)放在内存中,这是我无法负担的 name index change A Q QQ A Q QQ A Q QQ B L LL C Q QQ C L LL C LL LL C Q QQ C L LL C LL LL “名称”列的排序很好,我一次只关心一个名称。我希望在“更改”列上使用以下标准
name index change
A Q QQ
A Q QQ
A Q QQ
B L LL
C Q QQ
C L LL
C LL LL
C Q QQ
C L LL
C LL LL
“名称”列的排序很好,我一次只关心一个名称。我希望在“更改”列上使用以下标准来筛选每个名称:
name index change
A Q QQ
A Q QQ
A Q QQ
C L LL
C LL LL
C L LL
C LL LL
name index change
A Q QQ
A Q QQ
A Q QQ
name index change
A Q QQ
A Q QQ
A Q QQ
C L LL
C LL LL
C L LL
C LL LL
name index change
A Q QQ
A Q QQ
A Q QQ
我想知道是否有一种方法可以按名称处理表名,并在每个名称后释放内存。(而且不必一步一步地做这两个标准。)任何提示或建议都将不胜感激 因为文件是按“名称”排序的,所以您可以逐行读取文件:
def process_name(name, data, output_file):
group_by = {}
for index, change in data:
if index not in group_by:
group_by[index] = []
group_by[index].append(change)
# do the step 1 filter logic here
# do the step 2 filter logic here
for index in group_by:
if index == group_by[index]:
# Because there is at least one "no change" this
# whole "name" can be thrown out, so return here.
return
output = []
for index in group_by:
output_file.write("%s\t%s\t%s\n" % (name, index, group_by[index]))
current_name = None
current_data = []
input_file = open(input_filename, "r")
output_file = open(output_filename, "w")
header = input_file.readline()
for row in input_file:
cols = row.strip().split("\t")
name = cols[0]
index = cols[1]
change = cols[2]
if name != current_name:
if name != None:
process_name(current_name, current_data, output_file)
current_name = name
current_data = []
current_data.append((index, change))
# process what's left in the buffer
if current_name is not None:
process_name(current_name, current_data, output_file)
input_file.close()
output_file.close()
我不完全理解你在#1中解释的逻辑,所以我把它留白了。我还觉得您可能希望首先执行步骤2,因为这将很快排除整个“名称”的可能性。因为您的文件已排序,并且您似乎只按名称对子段进行操作,也许只需使用Python并在运行时为每个名称段创建一个表:
from itertools import groupby
import pandas as pd
with open('/tmp/so.csv') as f:
header=next(f).split()
for k, segment in groupby(f, key=lambda line: line.split()[0]):
seg_data={k:[] for k in header}
for e in segment:
for key, v in zip(header, e.split()):
seg_data[key].append(v)
seg_fram=pd.DataFrame.from_dict(seg_data)
print k
print seg_fram
print
印刷品:
A
change index name
0 QQ Q A
1 QQ Q A
2 QQ Q A
B
change index name
0 LL L B
C
change index name
0 QQ Q C
1 LL L C
2 LL LL C
3 QQ Q C
4 LL L C
5 LL LL C
然后,您将拥有的最大内存将由最大的连续组决定,而不是由文件大小决定
通过逐行追加到数据帧,而不是构建中间dict,可以使用该方法的1/2内存:
with open('/tmp/so.csv') as f:
header=next(f).split()
for k, segment in groupby(f, key=lambda line: line.split()[0]):
seg_data={k:[] for k in header}
seg_fram=pd.DataFrame(columns=header)
for idx, e in enumerate(segment):
df=pd.DataFrame({k:v for k, v in zip(header, e.split())}, index=[idx])
seg_fram=seg_fram.append(df)
(可能会慢一些…)
如果不起作用,请考虑使用磁盘数据库。 设法把规则编成法典。逐行读取文件,逐行累加,直到名称更改。在文件中保存该位置。处理已累积的行,应用规则,将结果附加到新文件。重复你在文件中留下的开始部分。考虑使用Awesome-非常感谢。我对我的问题做了一些修改,希望第一步更清楚——但现在不要担心,让我先回家消化一下你的代码。对于规则1,你是在谈论“索引”还是“更改”中的值?Q、L、QQ和LL是唯一可能的值吗?谢谢@georgeoflages的帮助。在仔细阅读了您的代码之后,我解决了这个问题-我认为关键是使用字典和键的概念,这是我还没有练习过的。不要担心规则1:)谢谢你@dawg!对不起,我迟了答复。我喜欢你关于使用1/2内存的想法,我很快就会尝试一下。我感谢你的帮助。