如何使用Pandas处理大型CSV文件?
在本文中,我们将介绍使用Pandas处理大型CSV文件的选项.CSV文件是数据的常见容器,如果您有一个大型CSV文件要有效处理熊猫,则有一些选择。
熊猫是一种内存工具
您需要能够将数据容纳在内存中,才能与熊猫一起使用。如果您一次可以处理其中的一部分,则可以将其读取成块并处理每个块。或者,如果您知道应该有足够的内存来加载文件,则有一些提示可以帮助减少文件大小。
请注意,通常,您的内存量应为要处理的DataFrame大小的三到十倍。额外的内存应为您提供足够的额外空间来执行许多常见操作。
1.使用Python检查系统的内存
让我们从检查系统内存开始。psutil将在Windows,MAC和Linux上运行。psutil可以通过pipinstall从Python的软件包管理器下载。
如果安装时psutil出现编译错误,请尝试以下步骤。须藤yum安装python3-devel须藤pip安装psutil
现在使用检查版本
点冻结greppsutil
输入项
import psutil memory = psutil.virtual_memory() print(f" {'*' * 3} Memory used percentage - {memory.percent} \n {'*' * 4} Free Memory available - { round(memory.free / (1024.0 ** 3))} GB")
***内存使用百分比-64.4
****可用内存-6GB
2.确定我们的csv文件的内存使用情况
现在,我们将估计整个文件将占用多少内存。我使用了来自kaggle.com的tmdb_5000_movies数据集。
输入项
import pandas as pd data = pd.read_csv("tmdb_5000_movies.csv") # Lets check the memory usage of the file print(f" ** Memory usage of the file - {sum(data.memory_usage()) * 0.000001} MB for {len(data.index)} Rows")
**文件的内存使用量-52833行为8.453408MB
data.memory_usage()方法显示了数据帧的内存使用情况,而len(data.index)显示了数据帧的总行数。
我们可以看到52833行使用了大约8MB以上的内存。如果我们有十亿行,那将需要大约151+GB的内存。现在,将所有内容放入内存并使其挂起是个坏主意,请不要这样做。
现在,让我们看一下这些数据类型的限制。
示例
import numpy as np # Limits of Integer Data Type print(f" ** Output limits of Numpy Integer Data Types ") print(f" ** limits of Numpy Integer - {np.iinfo(np.int8)}") print(f" ** limits of Numpy Integer - {np.iinfo(np.int16)}") print(f" ** limits of Numpy Integer - {np.iinfo(np.int64)}") # Limits of Float Data Type print(f" ** Output limits of Numpy Float Data Types ") print(f" ** limits of Numpy Float - {np.finfo(np.float16)}") print(f" ** limits of Numpy Float - {np.finfo(np.float64)}")
输出结果
** Output limits of Numpy Integer Data Types ** limits of Numpy Integer - Machine parameters for int8 --------------------------------------------------------------- min = -128 max = 127 --------------------------------------------------------------- ** limits of Numpy Integer - Machine parameters for int16 --------------------------------------------------------------- min = -32768 max = 32767 --------------------------------------------------------------- ** limits of Numpy Integer - Machine parameters for int64 --------------------------------------------------------------- min = -9223372036854775808 max = 9223372036854775807 --------------------------------------------------------------- ** Output limits of Numpy Float Data Types ** limits of Numpy Float - Machine parameters for float16 --------------------------------------------------------------- precision = 3 resolution = 1.00040e-03 machep = -10 eps = 9.76562e-04 negep = -11 epsneg = 4.88281e-04 minexp = -14 tiny = 6.10352e-05 maxexp = 16 max = 6.55040e+04 nexp = 5 min = -max --------------------------------------------------------------- ** limits of Numpy Float - Machine parameters for float64 --------------------------------------------------------------- precision = 15 resolution = 1.0000000000000001e-15 machep = -52 eps = 2.2204460492503131e-16 negep = -53 epsneg = 1.1102230246251565e-16 minexp = -1022 tiny = 2.2250738585072014e-308 maxexp = 1024 max = 1.7976931348623157e+308 nexp = 11 min = -max ---------------------------------------------------------------
输入项
**3.Converting Numeric Data Types** Let’s run the .info() method to validate our data types in depth. File "<ipython−input−17−aad3ab034212>", line 1 **3.Converting Numeric Data Types** ^ SyntaxError: invalid syntax
输入项
# Lets print the DataFrame information print(f" {data.info()}")
现在,让我们总结一下数据类型和列数,看看pandas如何对我们的数据进行分类。
输入项
# lets summarize the data types and count of columns print(f" ** Summarize the data types and count of columns \n{data.dtypes.value_counts()}")
在本节中,我们将重点介绍int64和float64数据类型,研究数据/精度并进行转换。我将使用dtype参数告诉熊猫使用较小的数字类型,而不是默认的64位,现在您了解了为什么首先了解数据类型的上述步骤很重要。
输入项
# Define a dictionary converting the numeric data types data_types_conversion_numeric = { "popularity": np.float16, "runtime": np.float16, "vote_average": np.float16, "id": np.int16, "revenue": np.int16, "vote_count": np.int16 } data_02 = pd.read_csv("tmdb_5000_movies.csv", dtype=data_types_conversion_numeric) print(f" ** Memory usage of the file - {sum(data_02.memory_usage()) * 0.000001} MB for {len(data_02.index)} Rows")
如您所见,通过将数据类型更改为使用较小的数字类型已为我们节省了23%的费用,如果您持有的数据量较小,则还可以使用int8,这可能会进一步节省费用。
4,转换对象数据类型
对象数据类型将值视为字符串。大熊猫中的字符串值占用大量内存,因为每个值都以Python字符串形式存储。如果该列证明是非数字的,大熊猫会将其转换为对象列。
将Pandas仅将字符串存储一次,而不是为每一行创建新的字符串,将Object数据类型转换为分类将占用更少的内存。
首先,检查对象列的.value_counts方法。您可以将它们转换为分类列,以节省更多内存。如果基数较低,
输入项
print(data_02.original_language.value_counts())
基数不是很高,我将开始将Object数据类型转换为Category。
输入项
data_types_conversion_numeric = { "popularity": np.float16, "runtime": np.float16, "vote_average": np.float16, "id": np.int16, "revenue": np.int16, "vote_count": np.int16, "genres": "category", "homepage": "category", "keywords": "category", "original_language": "category", "original_title": "category", "overview": "category", "production_companies": "category", "production_countries": "category", "release_date": "category", "spoken_languages": "category", "status": "category", "tagline": "category", "title": "category" } data_02 = pd.read_csv("tmdb_5000_movies.csv", dtype=data_types_conversion_numeric) print(f" ** Memory usage of the file - {sum(data_02.memory_usage()) * 0.000001} MB for {len(data_02.index)} Rows")
我们现在是原始大小的46%。大约节省了54%的内存。
5,识别和删除大熊猫中的重复项
您正在处理的源文件中很可能存在重复项,如果不需要,将其删除将为您节省更多的内存。就我而言,要使文件大小变大,我必须重复记录
让我们在删除源文件之前验证其数量。
输入项
print(f" ** File has {len(data_02) - len(data_02.drop_duplicates())} duplicate rows off the total {len(data_02)} ")
len(您的数据帧)输出数据帧中的总行,而len(dataframe.drop_duplicates())将输出数据帧中的唯一值。因此,如上,我的文件中有很多重复项,将其删除会节省大量内存。
输入项
data_03 = data_02.drop_duplicates() print(f" ** Memory usage of the file after dropping duplicates - {sum(data_03.memory_usage()) * 0.000001} MB for {len(data_03.index)} Rows")
好吧,删除重复项后可以节省一些钱。如果您有重复项并希望将其删除,请使用此步骤。
6,如何删除熊猫中不需要的列
If there are columns that you know can be ignored, then specify usecols parameter to include the columns you want to load. Here, we will ignore the columns “homepage”, “keywords”, “original_title” and “tagline”.
输入项
# prepare a list of columns that you want to load unwanted_columns = ["homepage", "keywords","original_title", "tagline"] data_columns = [columns for columns in list(pd.read_csv("tmdb_5000_movies.csv").columns) if columns not in unwanted_columns] # Define a dictionary converting the numeric data types data_types_conversion = { "popularity": np.float16, "runtime": np.float16, "vote_average": np.float16, "id": np.int16, "revenue": np.int16, "vote_count": np.int16, "genres": "category", "original_language": "category", "overview": "category", "production_companies": "category", "production_countries": "category", "release_date": "category", "spoken_languages": "category", "status": "category", "title": "category" } data_02 = pd.read_csv("tmdb_5000_movies.csv", dtype=data_types_conversion, usecols=data_columns) print(f" ** Memory usage of the file after dropping cols - {sum(data_02.memory_usage()) * 0.000001} MB for {len(data_02.index)} Rows")
我们现在是原始大小的32%。大约节省了68%的内存。
7,如何使用Pandas处理数据块
如果您可以一次处理数据块,并且不需要在内存中存储所有数据,则可以使用“块大小”参数。我个人建议将此作为您的最后选择。
# read the csv file data = pd.read_csv("tmdb_5000_movies.csv") # prepare a list of columns that you want to load unwanted_columns = ["homepage", "keywords","original_title", "tagline"] data_columns = [columns for columns in list(pd.read_csv("tmdb_5000_movies.csv").columns) if columns not in unwanted_columns] # Define a dictionary converting the numeric data types data_types_conversion = { "popularity": np.float16, "runtime": np.float16, "vote_average": np.float16, "id": np.int16, "revenue": np.int16, "vote_count": np.int16, "genres": "category", "original_language": "category", "overview": "category", "production_companies": "category", "production_countries": "category", "release_date": "category", "spoken_languages": "category", "status": "category", "title": "category" } data_02 = pd.read_csv("tmdb_5000_movies.csv", dtype=data_types_conversion, usecols=data_columns,chunksize=10000) # Process the data frame in chunks for chunk in data_02: print(f" ** Memory usage of the file after dropping cols − {sum(chunk.memory_usage()) * 0.000001} MB for {len(chunk.index)} Rows") print(f"Do some more processing here... ")
我们现在是原始大小的14%。大约节省了86%的内存。
注意-使用.describe()方法来持续比较每个步骤的结果。