在熊猫中使用chunksize读取不适合内存的大尺寸csv文件

时间:2020-01-21 06:08:34

标签: python pandas csv

我正在尝试使用不适合内存的熊猫读取大尺寸的csv文件,并从中创建单词频率,当整个文件都适合内存时,我的代码可以工作,但是定义块大小时却无法检查前面的块,以了解单词是否存在,如果单词不存在,只需增加它的频率即可,只需将其附加到文件末尾即可。不管前面的块里面有什么,它都会单独执行每个块,我正在尝试的代码是

dic = pd.DataFrame()
for chunk in pd.read_csv(fileinput, names=['sentences'], skiprows=skip, chunksize=1):
    dic_tmp = (chunk['sentences'].str.split(expand=True).stack().value_counts().rename_axis('word').reset_index(name='freq'))
    dic_tmp.append(dic)
dic.to_csv('nenene.csv', index=False, header=None)

出于测试目的,我将chunksize放在了一个小的csv文件中,该文件如下所示:

我得到的输出是:

enter image description here

而我想要得到的是这样的:

我在代码中做错了吗?有什么建议吗?

5 个答案:

答案 0 :(得分:1)

我认为您在dic_tmp.append(dic)上犯了一个错误,您需要的是dic = dic.append(dic_tmp)。另外,在单词之前,您将在输出中获取熊猫设置的索引,可以在to_csv()函数中使用index=False参数。

答案 1 :(得分:1)

这是您想做的事情:

chunks = pd.read_csv(fileinput, names=['sentences'], skiprows=skip, chunksize=chunksize)
d = pd.concat(chunks)
d2 = d['sentences'].str.split(expand=True).stack().value_counts().rename_axis('word').reset_index(name='freq')

在读取大文件时避免不必要的循环也会加快代码的速度

答案 2 :(得分:1)

您正在重置每个块中的频率。

您可以为此使用Counter。在开始时创建一个计数器对象。在每个块中,通过其update方法更新您的计数器。最后,根据需要将counter.most_common()的输出记录到文件中。

更新: 一个例子是:

import pandas as pd
from collections import Counter

c = Counter([]) # initiate counter with an empty list so we can update it later

chunks = pd.read_csv("/home/emre/Desktop/hdd/foo.csv", chunksize=1)

for chunk in chunks:
    for i, row in chunk.iterrows():
        c.update(row['sentences'].split(' '))

print(c.most_common())

输出为:

[('fly', 4),
 ('alex', 2),
 ('ibrahim', 2),
 ('hi', 1),
 ('my', 1),
 ('name', 1),
 ('is', 1),
 ('i', 1),
 ('am', 1),
 ('how', 1),
 ('are', 1),
 ('you', 1),
 ('doing', 1)]

现在,您可以遍历最常见的内容并将其保存到文件中

with open('most_commons.txt', 'w+') as f:
    for word_freq in c.most_common():
        f.write(word_freq[0] + ' ' + str(word_freq[1]) + '\n')

文件:

fly 4
alex 2
ibrahim 2
hi 1
my 1
name 1
is 1
i 1
am 1
how 1
are 1
you 1
doing 1

这样,您就不必制作chunksize=1。使其像chunksize=1000一样,这样就不必从磁盘读取文件太多次了。

写文件部分可能写得更优雅;只是为了演示。

答案 3 :(得分:1)

您对使用大熊猫的追求是什么?

也许您可以逐行读取文件并每次更新集合计数器。

import collections

freq = collections.Counter()
with open(filename) as f:
  for line in f:
    freq.update(line.split())

在此python块之后,您将获得varibale freq中的频率

答案 4 :(得分:1)

您可以简单地按创建的df分组:

输入:

   word  freq
0   fly     3
1  Alex     1
2  name     1
0  Alex     1
1   fly     1

df.groupby('word').sum()

输出:

       freq
word      
Alex     2
fly      4
name     1

完整示例:

dic = pd.DataFrame()
for chunk in pd.read_csv(fileinput, names=['sentences'], skiprows=skip, chunksize=1):
    dic_tmp = (chunk['sentences'].str.split(expand=True).stack().value_counts().rename_axis('word').reset_index(name='freq'))
    dic = dic.append(dic_tmp)
dic = dic.groupby('word').sum().reset_index().sort_values('freq',ascending=False)
dic.to_csv('nenene.csv', index=False, header=None)