我试图读取一个大的csv文件(aprox。6 GB)在熊猫和我得到一个内存错误:
MemoryError Traceback (most recent call last)
<ipython-input-58-67a72687871b> in <module>()
----> 1 data=pd.read_csv('aphro.csv',sep=';')
...
MemoryError:
有什么帮助吗?
我试图读取一个大的csv文件(aprox。6 GB)在熊猫和我得到一个内存错误:
MemoryError Traceback (most recent call last)
<ipython-input-58-67a72687871b> in <module>()
----> 1 data=pd.read_csv('aphro.csv',sep=';')
...
MemoryError:
有什么帮助吗?
当前回答
我想在已经提供的大多数潜在解决方案的基础上,给出一个更全面的答案。我还想指出另一个可能有助于阅读的方法。
选项1:dtypes
"dtypes"是一个非常强大的参数,您可以使用它来减少读取方法的内存压力。看看这个和这个答案。默认情况下,Pandas尝试推断数据的dtype。
根据数据结构,每存储一个数据,就进行一次内存分配。在基本层面上,请参考以下值(下表说明了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
请参阅本页查看NumPy和C类型之间的匹配。
假设你有一个整数数组。你可以在理论上和实际中分配,比如说一个16位整数类型的数组,但是你会分配比实际需要更多的内存来存储这个数组。为了避免这种情况,您可以在read_csv上设置dtype选项。你不想把数组项存储为长整数,实际上你可以用8位整数(np.int8或np.uint8)来适合它们。
观察下面的dtype映射。
来源:https://pbpython.com/pandas_dtypes.html
你可以将dtype参数作为参数传递给pandas方法,就像读取{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)
选项2:按块读取
以块形式读取数据允许您访问内存中的一部分数据,并且可以对数据应用预处理并保存处理过的数据而不是原始数据。如果将这个选项与第一个选项dtypes结合使用,效果会好得多。
我想指出熊猫烹饪书中关于这一过程的部分,你可以在这里找到。注意这两个部分;
逐块读取csv文件 逐块读取csv中的特定行
选项3:Dask
Dask是一个框架,在Dask的网站上定义为:
Dask为分析提供了高级的并行性,为您喜爱的工具提供了大规模的性能
它的诞生是为了覆盖熊猫无法到达的必要部位。Dask是一个功能强大的框架,通过以分布式方式处理数据,允许您访问更多的数据。
你可以使用dask来预处理你的数据作为一个整体,dask负责分块部分,所以不像pandas,你可以只定义你的处理步骤,让dask来做工作。Dask在被compute和/或persist显式地推入之前不会应用计算(请参阅这里的答案了解区别)。
其他辅助(想法)
ETL流程为数据设计。只保留原始数据中需要的内容。 首先,使用Dask或PySpark等框架将ETL应用于整个数据,并导出处理后的数据。 然后看看处理过的数据是否能整体地放入内存中。 考虑增加内存。 考虑在云平台上使用这些数据。
其他回答
函数read_csv和read_table几乎是一样的。但在程序中使用read_table函数时,必须分配分隔符“,”。
def get_from_action_data(fname, chunk_size=100000):
reader = pd.read_csv(fname, header=0, iterator=True)
chunks = []
loop = True
while loop:
try:
chunk = reader.get_chunk(chunk_size)[["user_id", "type"]]
chunks.append(chunk)
except StopIteration:
loop = False
print("Iteration is stopped")
df_ac = pd.concat(chunks, ignore_index=True)
下面是一个例子:
chunkTemp = []
queryTemp = []
query = pd.DataFrame()
for chunk in pd.read_csv(file, header=0, chunksize=<your_chunksize>, iterator=True, low_memory=False):
#REPLACING BLANK SPACES AT COLUMNS' NAMES FOR SQL OPTIMIZATION
chunk = chunk.rename(columns = {c: c.replace(' ', '') for c in chunk.columns})
#YOU CAN EITHER:
#1)BUFFER THE CHUNKS IN ORDER TO LOAD YOUR WHOLE DATASET
chunkTemp.append(chunk)
#2)DO YOUR PROCESSING OVER A CHUNK AND STORE THE RESULT OF IT
query = chunk[chunk[<column_name>].str.startswith(<some_pattern>)]
#BUFFERING PROCESSED DATA
queryTemp.append(query)
#! NEVER DO pd.concat OR pd.DataFrame() INSIDE A LOOP
print("Database: CONCATENATING CHUNKS INTO A SINGLE DATAFRAME")
chunk = pd.concat(chunkTemp)
print("Database: LOADED")
#CONCATENATING PROCESSED DATA
query = pd.concat(queryTemp)
print(query)
除了上面的答案,对于那些想要处理CSV然后导出到CSV、parquet或SQL的人来说,d6tstack是另一个不错的选择。您可以加载多个文件,它处理数据模式更改(添加/删除列)。核心支持已经被剔除。
def apply(dfg):
# do stuff
return dfg
c = d6tstack.combine_csv.CombinerCSV([bigfile.csv], apply_after_read=apply, sep=',', chunksize=1e6)
# or
c = d6tstack.combine_csv.CombinerCSV(glob.glob('*.csv'), apply_after_read=apply, chunksize=1e6)
# output to various formats, automatically chunked to reduce memory consumption
c.to_csv_combine(filename='out.csv')
c.to_parquet_combine(filename='out.pq')
c.to_psql_combine('postgresql+psycopg2://usr:pwd@localhost/db', 'tablename') # fast for postgres
c.to_mysql_combine('mysql+mysqlconnector://usr:pwd@localhost/db', 'tablename') # fast for mysql
c.to_sql_combine('postgresql+psycopg2://usr:pwd@localhost/db', 'tablename') # slow but flexible
我是这样说的:
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)
解决方案1:
使用大数据的熊猫
解决方案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)