Raj*_*wat 166 python memory csv chunks pandas
我试图在pandas中读取一个大的csv文件(aprox.6 GB),我收到以下内存错误:
MemoryError Traceback (most recent call last)
<ipython-input-58-67a72687871b> in <module>()
----> 1 data=pd.read_csv('aphro.csv',sep=';')
C:\Python27\lib\site-packages\pandas\io\parsers.pyc in parser_f(filepath_or_buffer, sep, dialect, compression, doublequote, escapechar, quotechar, quoting, skipinitialspace, lineterminator, header, index_col, names, prefix, skiprows, skipfooter, skip_footer, na_values, na_fvalues, true_values, false_values, delimiter, converters, dtype, usecols, engine, delim_whitespace, as_recarray, na_filter, compact_ints, use_unsigned, low_memory, buffer_lines, warn_bad_lines, error_bad_lines, keep_default_na, thousands, comment, decimal, parse_dates, keep_date_col, dayfirst, date_parser, memory_map, nrows, iterator, chunksize, verbose, encoding, squeeze, mangle_dupe_cols, tupleize_cols, infer_datetime_format)
450 infer_datetime_format=infer_datetime_format)
451
--> 452 return _read(filepath_or_buffer, kwds)
453
454 parser_f.__name__ = name
C:\Python27\lib\site-packages\pandas\io\parsers.pyc in _read(filepath_or_buffer, kwds)
242 return parser
243
--> 244 return parser.read()
245
246 _parser_defaults = {
C:\Python27\lib\site-packages\pandas\io\parsers.pyc in read(self, nrows)
693 raise ValueError('skip_footer not supported for iteration')
694
--> 695 ret = self._engine.read(nrows)
696
697 if self.options.get('as_recarray'):
C:\Python27\lib\site-packages\pandas\io\parsers.pyc in read(self, nrows)
1137
1138 try:
-> 1139 data = self._reader.read(nrows)
1140 except StopIteration:
1141 if nrows is None:
C:\Python27\lib\site-packages\pandas\parser.pyd in pandas.parser.TextReader.read (pandas\parser.c:7145)()
C:\Python27\lib\site-packages\pandas\parser.pyd in pandas.parser.TextReader._read_low_memory (pandas\parser.c:7369)()
C:\Python27\lib\site-packages\pandas\parser.pyd in pandas.parser.TextReader._read_rows (pandas\parser.c:8194)()
C:\Python27\lib\site-packages\pandas\parser.pyd in pandas.parser.TextReader._convert_column_data (pandas\parser.c:9402)()
C:\Python27\lib\site-packages\pandas\parser.pyd in pandas.parser.TextReader._convert_tokens (pandas\parser.c:10057)()
C:\Python27\lib\site-packages\pandas\parser.pyd in pandas.parser.TextReader._convert_with_dtype (pandas\parser.c:10361)()
C:\Python27\lib\site-packages\pandas\parser.pyd in pandas.parser._try_int64 (pandas\parser.c:17806)()
MemoryError:
Run Code Online (Sandbox Code Playgroud)
对此有何帮助??
unu*_*tbu 216
该错误表明机器没有足够的内存来将整个CSV一次读入DataFrame.假设您一次不需要内存中的整个数据集,避免此问题的一种方法是以块的形式处理CSV(通过指定chunksize
参数):
chunksize = 10 ** 6
for chunk in pd.read_csv(filename, chunksize=chunksize):
process(chunk)
Run Code Online (Sandbox Code Playgroud)
该chucksize
参数指定每个块的行数.(当然,最后一个块可能包含少于chunksize
行.)
jpp*_*jpp 63
分块不应该总是这个问题的第一个停靠点.
1.由于重复的非数字数据或不需要的列,文件是否很大?
如果是这样,您有时可以通过读取列作为类别并通过pd.read_csv usecols
参数选择所需列来节省大量内存.
2.您的工作流程是否需要切片,操作,导出?
如果是这样,您可以使用dask.dataframe进行切片,执行计算并迭代导出.通过dask静默执行分块,它也支持pandas API的子集.
3.如果所有其他方法都失败了,请通过块逐行读取.
Raj*_*wat 33
我继续这样做:
chunks=pd.read_table('aphro.csv',chunksize=1000000,sep=';',\
names=['lat','long','rf','date','slno'],index_col='slno',\
header=None,parse_dates=['date'])
df=pd.DataFrame()
%time df=pd.concat(chunk.groupby(['lat','long',chunk['date'].map(lambda x: x.year)])['rf'].agg(['sum']) for chunk in chunks)
Run Code Online (Sandbox Code Playgroud)
Sim*_*tsi 27
对于大数据,我建议您使用库"dask",
例如:
# Dataframes implement the Pandas API
import dask.dataframe as dd
df = dd.read_csv('s3://.../2018-*-*.csv')
Run Code Online (Sandbox Code Playgroud)
我想根据已经提供的大多数潜在解决方案做出更全面的答案。我还想指出另一种可能有助于阅读过程的潜在帮助。
选项 1:dtypes
“dtypes”是一个非常强大的参数,您可以使用它来减少read
方法的内存压力。看到这个和这个答案。默认情况下,熊猫会尝试推断数据的 dtypes。
参考数据结构,存储的每个数据,都会发生内存分配。在基本级别,请参考以下值(下表说明了 C 编程语言的值):
The maximum value of UNSIGNED CHAR = 255
The minimum value of SHORT INT = -32768
The maximum value of SHORT INT = 32767
The minimum value of INT = -2147483648
The maximum value of INT = 2147483647
The minimum value of CHAR = -128
The maximum value of CHAR = 127
The minimum value of LONG = -9223372036854775808
The maximum value of LONG = 9223372036854775807
Run Code Online (Sandbox Code Playgroud)
请参阅此页面以查看 NumPy 和 C 类型之间的匹配。
假设您有一个由数字组成的整数数组。您可以在理论上和实际上分配,例如 16 位整数类型的数组,但是您将分配比实际需要存储该数组更多的内存。为了防止这种情况,您可以dtype
在 上设置选项read_csv
。您不想将数组项存储为长整数,而实际上您可以用 8 位整数(np.int8
或np.uint8
)来拟合它们。
观察以下 dtype 映射。
来源:https : //pbpython.com/pandas_dtypes.html
您可以将dtype
参数作为 Pandas 方法的参数作为 dict传递给read
{column: type}。
import numpy as np
import pandas as pd
df_dtype = {
"column_1": int,
"column_2": str,
"column_3": np.int16,
"column_4": np.uint8,
...
"column_n": np.float32
}
df = pd.read_csv('path/to/file', dtype=df_dtype)
Run Code Online (Sandbox Code Playgroud)
选项 2:按块读取
以块的形式读取数据允许您访问内存中的部分数据,并且您可以对数据应用预处理并保留处理后的数据而不是原始数据。如果将此选项与第一个选项dtypes结合使用会更好。
我想指出该过程的熊猫食谱部分,您可以在此处找到它。注意那里的那两个部分;
选项 3:Dask
Dask 是一个框架,在Dask 的网站上定义为:
Dask 为分析提供高级并行性,为您喜爱的工具提供大规模性能
它的诞生是为了覆盖熊猫无法到达的必要部分。Dask 是一个强大的框架,它允许您通过以分布式方式处理数据来访问更多数据。
您可以使用 dask 对整个数据进行预处理,Dask 负责分块部分,因此与 Pandas 不同,您只需定义处理步骤并让 Dask 完成工作。Dask 在被compute
和/或明确推送之前不会应用计算persist
(有关差异,请参阅此处的答案)。
其他帮助(想法)
在使用 chunksize 选项之前,如果您想确定要在分块 for 循环内编写的处理函数(如 @unutbu 提到的),您可以简单地使用 nrows 选项。
small_df = pd.read_csv(filename, nrows=100)
Run Code Online (Sandbox Code Playgroud)
一旦确定流程块已准备好,您就可以将其放入整个数据帧的分块 for 循环中。
小智 6
read_csv 和 read_table 函数几乎相同。但在程序中使用 read_table 函数时,必须指定分隔符 \xe2\x80\x9c\xef\xbc\x8c\xe2\x80\x9d。
\n\ndef get_from_action_data(fname, chunk_size=100000):\n reader = pd.read_csv(fname, header=0, iterator=True)\n chunks = []\n loop = True\n while loop:\n try:\n chunk = reader.get_chunk(chunk_size)[["user_id", "type"]]\n chunks.append(chunk)\n except StopIteration:\n loop = False\n print("Iteration is stopped")\n\n df_ac = pd.concat(chunks, ignore_index=True)\n
Run Code Online (Sandbox Code Playgroud)\n
小智 6
您可以将数据读取为大块,并将每个大块另存为泡菜。
import pandas as pd
import pickle
in_path = "" #Path where the large file is
out_path = "" #Path to save the pickle files to
chunk_size = 400000 #size of chunks relies on your available memory
separator = "~"
reader = pd.read_csv(in_path,sep=separator,chunksize=chunk_size,
low_memory=False)
for i, chunk in enumerate(reader):
out_file = out_path + "/data_{}.pkl".format(i+1)
with open(out_file, "wb") as f:
pickle.dump(chunk,f,pickle.HIGHEST_PROTOCOL)
Run Code Online (Sandbox Code Playgroud)
在下一步中,您将读取泡菜并将每个泡菜附加到所需的数据框中。
import glob
pickle_path = "" #Same Path as out_path i.e. where the pickle files are
data_p_files=[]
for name in glob.glob(pickle_path + "/data_*.pkl"):
data_p_files.append(name)
df = pd.DataFrame([])
for i in range(len(data_p_files)):
df = df.append(pd.read_pickle(data_p_files[i]),ignore_index=True)
Run Code Online (Sandbox Code Playgroud)
解决方案一:
解决方案2:
TextFileReader = pd.read_csv(path, chunksize=1000) # the number of rows per chunk
dfList = []
for df in TextFileReader:
dfList.append(df)
df = pd.concat(dfList,sort=False)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
181444 次 |
最近记录: |