我编写了一段代码,将 DataFrame 的各个部分连接到同一个 DataFrame,以便根据特定列规范行的出现。
import random
def normalize(data, expectation):
"""Normalize data by duplicating existing rows"""
counts = data[expectation].value_counts()
max_count = int(counts.max())
for tag, group in data.groupby(expectation, sort=False):
array = pandas.DataFrame(columns=data.columns.values)
i = 0
while i < (max_count // int(counts[tag])):
array = pandas.concat([array, group])
i += 1
i = max_count % counts[tag]
if i > 0:
array = pandas.concat([array, group.ix[random.sample(group.index, i)]])
data = pandas.concat([data, array])
return data
Run Code Online (Sandbox Code Playgroud)
这速度慢得令人难以置信。有没有一种方法可以快速连接 DataFrame 而无需创建它的副本?
有几件事很突出。
首先,循环
i = 0
while i < (max_count // int(counts[tag])):
array = pandas.concat([array, group])
i += 1
Run Code Online (Sandbox Code Playgroud)
会非常慢。Pandas 不是为这些动态串联而构建的,我怀疑性能对于你正在做的事情来说是二次方的。
相反,也许你可以尝试
pandas.concat([group] * (max_count // int(counts[tag]))
Run Code Online (Sandbox Code Playgroud)
它只是首先创建一个列表,然后调用concat整个列表的一次性串联。这应该使复杂性变得线性,并且我怀疑在任何情况下它都会具有较低的常数。
另一件可以减少这些小事的事情concats是调用groupby-apply. 不要迭代 的结果groupby,而是将循环体编写为函数并调用apply它。让 Pandas 找出如何将所有结果连接到单个 DataFrame 中的最佳方法。
然而,即使您更喜欢保留循环,我也只是将内容附加到列表中,并将concat所有内容放在最后:
stuff = []
for tag, group in data.groupby(expectation, sort=False):
# Call stuff.append for any DataFrame you were going to concat.
pandas.concat(stuff)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7860 次 |
| 最近记录: |