Python 快速 DataFrame 串联

mui*_*ine 6 python pandas

我编写了一段代码,将 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 而无需创建它的副本?

Ami*_*ory 5

有几件事很突出。


首先,循环

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)