python - 为什么在具有 2.5 亿行的数据框中搜索/评估对象列非常慢?
问题描述
我有一个 2.35 亿行的数据框。其中一列是具有城市名称的对象,例如芝加哥、卢森堡等。
当我做一个简单的熊猫过滤器时:
result = data[(data['CITY'] == 'Louxemburg')]
它需要永远。超过 1.5 小时。
当我按以下方式诉诸DASK时:
ddask = dd.from_pandas(data, npartitions=15)
result = ddask[(ddask['CITY'] == 'Louxemburg')].compute(scheduler='processes')
大约需要45分钟。
我真的认为这样一个简单的评估不应该花这么长时间。我错过了什么吗?
解决方案
我不确定你的数据有多大,但根据你分享的内容,我相信你的记忆有问题。如果您需要加载每个查询中的所有列,则可能没有任何工具可以帮助您。但是,如果您打算从某些列中提取信息,Bodo 可以让您的生活更轻松。本质上,Bodo 通过优化顺序操作来减少内存使用。例如,Bodo 通过不加载未使用的 Parquet 列来释放内存空间。您可以在此链接找到 Bodo 的安装说明:https ://docs.bodo.ai/latest/source/install.html
我稍微修改了您的代码并使用了三列而不是所有列。然后,我用 Pandas 运行了你的代码,运行了大约 6 分钟。你的数据一定比我的大得多,因为它需要超过 1.5 小时才能运行。为了提高代码的性能和可扩展性,我使用 Bodo 运行相同的代码,耗时不到 25 秒。
数据生成注意事项:我生成了一个包含 10 列和 2.35 亿行的大型数据集。然后,我添加了另一个名为 CITY 的列,其中随机填充了 24 个城市名称。为了使生成的数据更重,另外两列的行已替换为 CITY 列内容,然后将数据保存为 Parquet 文件。
#data generation
import pandas as pd
import numpy as np
import random
#making a 10 columns dataframe filled
df = pd.DataFrame(np.random.randn(235000000, 10), columns = list('ABCDEFGHIJ'))
#making the City column filled randomly from 24 city names
df['CITY'] = df['J'].apply(lambda x: random.choice(['Chicago', 'Tokyo', 'Delhi', 'Cairo',
'Dhaka', 'Mumbai', 'Beijing', 'Osaka',
'Mexico City', 'Shanghai', 'Sao Paulo',
'Los angeles', 'Boston', 'San Diego', 'Louxemburg',
'Austin', 'London', 'Denver', 'Pittsburgh',
'Orlando', 'Memphis', 'Phoenix', 'Tehran']))
#replacing two columns with CITY column
df['H'] = df['CITY']
df['I'] = df['CITY']
df.to_parquet("data.pq")
使用熊猫:
import time
import pandas as pd
import numpy as np
start = time.time()
df = pd.read_parquet("data.pq")
df = df[['A','B','CITY']]
result = df.loc[df['CITY'] == 'Louxemburg']
end = time.time()
print("computation time: ", end - start)
print(result.head())
output:
computation time: 322.3528618812561
A B CITY
1 -0.553538 1.214924 Louxemburg
16 1.191735 0.437258 Louxemburg
19 -0.973316 -0.220664 Louxemburg
27 0.481840 2.833082 Louxemburg
33 0.093671 0.142565 Louxemburg
与博多:
%%px
import pandas as pd
import numpy as np
import bodo
import time
@bodo.jit(distributed = ['df'])
def filter_data():
start = time.time()
df = pd.read_parquet("q3.pq")
df = df[['A','B','CITY']]
df = df.loc[df['CITY'] == 'Louxemburg']
end = time.time()
print("computation time: ", end - start)
print(df.head())
return df
df = filter_data()
output:
[stdout:0]
computation time: 24.971635405003326
A B CITY
1 -0.553538 1.214924 Louxemburg
16 1.191735 0.437258 Louxemburg
19 -0.973316 -0.220664 Louxemburg
27 0.481840 2.833082 Louxemburg
33 0.093671 0.142565 Louxemburg
免责声明:我在 Bodo.ai 担任数据科学家倡导者。
推荐阅读
- c++ - 如何在具有共享 OpenGL 上下文的 Qt 应用程序中有条件地指定 OpenGL ES 版本?
- javascript - 如果爱好在不同的组件中,则在渲染时使用 onClick 过滤项目的最佳方法是什么?
- swiftui - Xcode 13 SwiftUI 颜色文字丢失
- wordpress - 如何在 divi 代码块中使用 acf-number
- python - "
没有相应的文件和目录” - gitlab - 当包含 .yml 包含工作流规则时,CI 管道不会自动运行
- sapui5 - SAPUI5 与 SAP Business One (SQL Server)
- c# - 为什么只创建了一张表?
- css - wordpress中的英雄图像背景没有将它的孩子放在里面
- ruby - 在 ruby 中使用 octokit 在 github 中检索最新的发布版本和最后 3 个各自的提交