2016-02-12 54 views
2

我写了一个代码,将DataFrame的各个部分连接到同一个DataFrame,以便按照某个列标准化行的出现。Python快速DataFrame串联

def normalize(data, expectation): 
'Normalize data by duplicating existing rows' 

import random 

counts = data[expectation].value_counts() 
max_count = int(counts.max()) 

for tag, group in data.groupby(expectation, sort=False): 
    # data = pandas.concat([data, group.sample(max - len(group.index))]) azureml python version istoo old to have sample method 
    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而不创建它的副本?

+0

这看起来痛苦......这将是一个更容易如果您发布了一些示例数据,还可以回复。另外,你希望你的'conc'循环之外的concat。如果您将数组存储在列表中,然后在循环之后进行连接,则运行速度会更快。然而,再次,可能有一个更简单的方法来做到这一点。 – Alexander

回答

2

有几件事情是突出的。


首先,循环

i = 0 
while i < (max_count // int(counts[tag])): 
    array = pandas.concat([array, group]) 
    i += 1 

将是非常缓慢的。熊猫不是为这些动态连接而构建的,我怀疑你的工作性能是二次的。

相反,也许你可以尝试

pandas.concat([group] * (max_count // int(counts[tag])) 

刚刚创建一个列表,然后再对整个列表上一杆串联调用concat。这应该使线性复杂化,并且我怀疑在任何情况下都会有较低的常量。


这将降低这些小concats另一件事是打电话groupby-apply。代替迭代groupby的结果,将循环体写入一个函数,然后调用apply。让熊猫最清楚如何将所有结果连接到一个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)