【发布时间】:2016-12-12 21:01:18
【问题描述】:
tl;博士
我的问题是,当使用 Pandas DataFrames 作为组合图的一部分时,我一直在计算在完全外部合并的每个部分上预期有多少行。
问题(下文重复)。
- 理想的解决方案是不需要合并并查询
panel对象。鉴于panel上没有查询方法,是否有更简洁的解决方案可以在不达到内存上限的情况下解决此问题? - 如果对 2 的回答是否定的,我如何计算每个集合组合所需的合并表的大小而不执行合并?这可能是一种次优方法,但在这种情况下,它对于应用程序的目的来说是可以接受的。
- Python 是否适合这种情况,或者我应该寻找一种更具统计性的语言,例如
R还是在较低级别编写它(c,cython) - 数据库不在问题。
问题
最近我重新编写了py-upset graphing library,以便在计算跨 DataFrame 的组合时在时间方面更有效。我不是在寻找对此代码的审查,它在大多数情况下都运行良好,我对这种方法感到满意。我现在正在寻找的是一个非常具体的问题的答案;在处理大型数据集时发现。
我在重写时采用的方法是在内存中合并所有提供的数据帧,如480 - 502 of pyupset.resources 行所示的完全外部连接
for index, key in enumerate(keys):
frame = self._frames[key]
frame.columns = [
'{0}_{1}'.format(column, key)
if column not in self._unique_keys
else
column
for column in self._frames[key].columns
]
if index == 0:
self._merge = frame
else:
suffixes = (
'_{0}'.format(keys[index-1]),
'_{0}'.format(keys[index]),
)
self._merge = self._merge.merge(
frame,
on=self._unique_keys,
how='outer',
copy=False,
suffixes=suffixes
)
对于中小型数据帧,使用连接的效果非常好。事实上,最近的性能测试表明,它可以在不到一分钟的时间内处理 5 或 6 个数据集,每个数据集包含 10,000 行,这对于我需要的应用程序结构来说绰绰有余。
问题现在从基于时间转移到基于内存。
考虑到可能包含数千条记录的数据集,即使在大型服务器上,该库也会很快耗尽内存。
为了说明这一点,我的这个应用程序的测试机器是一个 8 核 VMWare 机器,具有 128GiB RAM,运行 Centos7。
鉴于以下数据集大小,当添加第 5 个数据帧时,内存使用量呈指数增长。这是非常出乎意料的,但强调了我面临的问题的核心。
Rows | Dataframe
------------------------
13963 | dataframe_one
48346 | dataframe_two
52356 | dataframe_three
337292 | dataframe_four
49936 | dataframe_five
24542 | dataframe_six
258093 | dataframe_seven
16337 | dataframe_eight
就行数而言,这些不是“小”数据帧,尽管每个数据帧的列数限制为一个唯一键 + 4 个非唯一列。 pandas中每一列的大小为
column | type | unique
--------------------------
X | object | Y
id | int64 | N
A | float64 | N
B | float64 | N
C | float64 | N
此合并可能会导致内存被耗尽。有时它会因 MemoryError 而中止(太好了,我可以捕捉并处理这些错误),有时内核会接管并在系统变得不稳定之前简单地杀死应用程序,有时,系统会挂起并变得无响应/不稳定,直到最终内核杀死应用程序并释放内存。
样本输出(内存大小近似):
[INFO] Creating merge table
[INFO] Merging table dataframe_one
[INFO] Data index length = 13963 # approx memory <500MiB
[INFO] Merging table dataframe_two
[INFO] Data index length = 98165 # approx memory <1.8GiB
[INFO] Merging table dataframe_three
[INFO] Data index length = 1296665 # approx memory <3.0GiB
[INFO] Merging table dataframe_four
[INFO] Data index length = 244776542 # approx memory ~13GiB
[INFO] Merging table dataframe_five
Killed # > 128GiB
当合并表产生后,以集合组合方式查询,产生类似https://github.com/mproffitt/py-upset/blob/feature/ISSUE-7-Severe-Performance-Degradation/tests/generated/extra_additional_pickle.png的图
我为解决内存问题而尝试构建的方法是查看为合并提供的集合,预先确定合并需要多少内存,然后如果该组合需要太多,则将其拆分为更小的组合,分别计算每一个,然后将最终的数据帧重新组合在一起(分而治之)。
我的问题是我一直在计算合并的每个部分预期的行数。
问题(从上面重复)
- 理想的解决方案是不需要合并并查询
panel对象。鉴于panel上没有查询方法,是否有更简洁的解决方案可以在不达到内存上限的情况下解决此问题? - 如果对 2 的回答是否定的,我如何计算每个集合组合所需的合并表的大小而不执行合并?这可能是一种次优方法,但在这种情况下,它对于应用程序的目的来说是可以接受的。
- Python 是否适合这方面的语言,或者我应该寻找一种更具统计性的语言,例如
R还是在较低级别编写它(c、cython)。
对冗长的问题表示歉意。如果需要或可能,我很乐意提供更多信息。
谁能解释一下这可能是什么原因?
谢谢。
【问题讨论】:
标签: python-3.x pandas merge combinatorics