我编写了一段代码,将 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
这慢得令人难以置信。有没有一种方法可以在不创建副本的情况下快速连接 DataFrame?
最佳答案
有几件事很突出。
首先,循环
i = 0
while i < (max_count // int(counts[tag])):
array = pandas.concat([array, group])
i += 1
会很慢。 Pandas 不是为这些动态连接而构建的,我怀疑性能是你正在做的事情的二次方。
相反,也许你可以试试
pandas.concat([group] * (max_count // int(counts[tag]))
它只是先创建一个列表,然后调用 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)
关于Python 快速 DataFrame 连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35367882/