Python:分解大文件,根据标准进行筛选,并将所有数据放入新的csv文件中



我有一个超大的csv.gzip文件,它有59个mill行。我想根据某些条件筛选该文件中的某些行,并将所有这些行放在一个新的主csv文件中。到目前为止,我将gzip文件分解为118个较小的csv文件,并将它们保存在我的计算机上。我用以下代码做到了这一点:

import pandas as pd
num = 0
df = pd.read_csv('google-us-data.csv.gz', header = None, 
compression =   'gzip', chunksize = 500000,
names = ['a','b','c','d','e','f','g','h','i','j','k','l','m'],
error_bad_lines = False, warn_bad_lines = False)
for chunk in df:
    num = num + 1
    chunk.to_csv('%ggoogle us'%num ,sep='t', encoding='utf-8'

上面的代码运行得很好,我现在有了一个文件夹,里面有118个小文件。然后,我编写了代码,逐一浏览118个文件,提取符合某些条件的行,并将它们全部附加到我创建的新csv文件中,并将其命名为"google final us"。这是代码:

import pandas as pd
import numpy
for i in range (1,118)
    file = open('google final us.csv','a')
    df = pd.read_csv('%ggoogle us'%i, error_bad_lines = False, 
    warn_bad_lines = False)
    df_f = df.loc[(df['a']==7) & (df['b'] == 2016) & (df['c'] =='D') & 
    df['d'] =='US')]
    file.write(df_f)

不幸的是,上面的代码给了我以下错误:

KeyError                                  Traceback (most recent call last)
C:Users...Anaconda3libsite-packagespandasindexesbase.py in
get_loc(self, key, method, tolerance)
   1875             try:
-> 1876                 return self._engine.get_loc(key)
   1877             except KeyError:
pandasindex.pyx in pandas.index.IndexEngine.get_loc (pandasindex.c:4027)()
pandasindex.pyx in pandas.index.IndexEngine.get_loc (pandasindex.c:3891)()
pandashashtable.pyx in pandas.hashtable.PyObjectHashTable.get_item  
(pandashashtable.c:12408)()
pandashashtable.pyx in pandas.hashtable.PyObjectHashTable.get_item 
(pandashashtable.c:12359)()
KeyError: 'a'
During handling of the above exception, another exception occurred:
KeyError                                  Traceback (most recent call last)
<ipython-input-9-0ace0da2fbc7> in <module>()
      3 file = open('google final us.csv','a')
      4 df = pd.read_csv('1google us')
----> 5 df_f = df.loc[(df['a']==7) & (df['b'] == 2016) & 
      (df['c'] =='D') & (df['d'] =='US')]
      6 file.write(df_f)
C:Users...Anaconda3libsite-packagespandascoreframe.py in 
__getitem__(self, key)
   1990             return self._getitem_multilevel(key)
   1991         else:
-> 1992             return self._getitem_column(key)
   1993 
   1994     def _getitem_column(self, key):
C:Users...Anaconda3libsite-packagespandascoreframe.py in 
_getitem_column(self, key)
   1997         # get column
   1998         if self.columns.is_unique:
-> 1999             return self._get_item_cache(key)
   2000 
   2001         # duplicate columns & possible reduce dimensionality
C:Users...Anaconda3libsite-packagespandascoregeneric.py in 
_get_item_cache(self, item)
  1343         res = cache.get(item)
  1344         if res is None:
-> 1345             values = self._data.get(item)
  1346             res = self._box_item_values(item, values)
  1347             cache[item] = res
C:Users...Anaconda3libsite-packagespandascoreinternals.py in 
get(self, item, fastpath)
   3223 
   3224             if not isnull(item):
-> 3225                 loc = self.items.get_loc(item)
   3226             else:
   3227                 indexer = np.arange(len(self.items)) 
 [isnull(self.items)]
C:Users...Anaconda3libsite-packagespandasindexesbase.py in 
get_loc(self, key, method, tolerance)
   1876                 return self._engine.get_loc(key)
   1877             except KeyError:
-> 1878                 return 
   self._engine.get_loc(self._maybe_cast_indexer(key))
   1879 
   1880         indexer = self.get_indexer([key], method=method, 
   tolerance=tolerance)
pandasindex.pyx in pandas.index.IndexEngine.get_loc (pandasindex.c:4027)()
pandasindex.pyx in pandas.index.IndexEngine.get_loc (pandasindex.c:3891)()
pandashashtable.pyx in pandas.hashtable.PyObjectHashTable.get_item 
(pandashashtable.c:12408)()
pandashashtable.pyx in pandas.hashtable.PyObjectHashTable.get_item  
(pandashashtable.c:12359)()
KeyError: 'a'

你知道怎么了吗?我读过很多其他stackerflow的文章(例如,通过跨多列筛选从唯一值对创建数据帧,或者我如何通过python将一个大的csv文件分解为基于公共记录的小文件(,但仍然不知道如何做到这一点。此外,如果你有比这种方法更好的方法来提取数据,请告诉我!

import pandas
import glob
csvFiles = glob.glob(path + "/split files/*.csv")
list_ = []
for files in csvFiles:
    df = pandas.read_csv(files, index_col=None)
    df_f = df[(df['a']==7) & (df['b'] == 2016) & (df['c'] =='D') & df['d']=='US')]
    list_.append(df_f)
frame = pandas.concat(list_, ignore_index=True)
frame.to_csv("Filtered Appended File")

保留工作目录中拆分文件文件夹中的所有文件。。。

这应该有效。。。通过读取目录中的所有必需文件

读取csv需要大量内存。。。因此,打破它们并对其进行处理是一个可能的解决方案。。。你似乎在正确的轨道上。。。

当您使用file.write(df_f(时,您有效地保存了DataFrame的字符串表示形式,这是为了让人们查看。默认情况下,该表示形式会截断行和列,以便大帧可以以合理的方式显示在屏幕上。因此,列"a"可能会被截断。

with open('google final us.csv','a') as file:
    for i in range(1, 118):
        headers = i == 1
        ...
        df_f.to_csv(file, headers=headers)

我没有测试上面的片段,但你现在应该知道如何开始了。

此代码还有其他问题,您可能需要更正:

  1. 在循环之前打开要写入的文件,然后关闭它。最好使用上下文管理器。

  2. 如果整个数据都在内存中,为什么要麻烦地将其拆分为118个文件?只需过滤它并使用df.to_csv((方法保存生成的DataFrame。

  3. 不要考虑熊猫使用csv。DictReader并在运行中过滤行

最后,如果这是一项一次性的工作,为什么还要写一些可以用grep命令(在类Unix系统上(完成的代码呢?

甚至可能不需要将巨大的CSV拆分为多个文件。您可以使用read_csv函数的iteratorchunksize选项(有关更高级的用法,请参阅文档(。

file_path = 'my_big_file.csv'
chunksize = 100000
df_chunks = []
for df in pd.read_csv(file_path, chunksize=chunksize, iterator=True):
    df_f = df.loc[(df['a']==7) & (df['b'] == 2016) & (df['c'] =='D') & 
df['d'] =='US')]
    df_chunks.append(df_f)
master_df = pd.concat(df_chunks)

还有一个low_memory选项也可以传递给read_csv

在内部按块处理文件,从而降低内存使用率在解析时,但可能是混合类型推理。确保不混合types设置为False,或使用dtype参数指定类型。注意,整个文件被读取到单个DataFrame中,使用chunksize或迭代器参数以块的形式返回数据。(仅适用于C语法分析器(

对于整个数据集上的一些更高级的操作(例如,您需要对一些数据集进行分组(,可能还值得考虑将数据输入到SQL数据库中并在那里进行操作——Panda在SQL读/写方面提供了一些支持。这里解释了一个很好的例子。

最新更新