我可以使用一些帮助来加速此代码块。我假设concat ops是使代码变慢的原因,但是我不确定。这个循环执行我函数中其余代码的时间大约是20倍。
df = pd.DataFrame()
for index, row in p_data_df.iterrows():
test_df = log_df.loc[row['Mid-C']].to_frame().transpose()
if 'S' not in test_df.columns:
test_df.insert(0, 'S', row.loc['S'])
test_df.insert(1, 'C #', row.loc['C #'])
test_df.insert(2, 'Num', row.loc['Num'])
df = pd.concat([df, test_df], axis=0)
答案 0 :(得分:2)
切勿在for循环内调用pd.concat
。它导致二次复制:concat
返回一个新的DataFrame。必须为新的DataFrame分配空间,并且必须将旧DataFrame中的数据复制到新的DataFrame中。
因此,如果您的数据帧具有N行,则完成循环需要O(N ^ 2)个副本。
使用字典列表或列表列表代替数据框来累积结果,并在for循环之外使用结果列表创建数据框。这样,您将节省大量执行时间,而熊猫并没有为此做。
这是您的方法:
list_res = []
for index, row in p_data_df.iterrows():
test_df = log_df.loc[row['Mid-C']].to_frame().transpose()
if 'S' not in test_df.columns:
test_df.insert(0, 'S', row.loc['S'])
test_df.insert(1, 'C #', row.loc['C #'])
test_df.insert(2, 'Num', row.loc['Num'])
list_res.append(test_df)
df = pd.concat(list_res, axis=0)
iterrows是用于迭代数据帧的最慢的方法,因为必须将每一行转换为一系列。如果您使用itertuples,则不会发生。您可以使用itertuples,而无需过多更改代码,但可以提高性能。
还有其他方法(矢量化,应用函数,Cython ...),它们需要对代码进行稍宽的修改,但可以使您拥有更高效的代码。我留下您this link,以获取更多信息。
答案 1 :(得分:1)
所使用的 <!-- Load Facebook SDK for JavaScript -->
<div id="fb-root"></div>
<script>
window.fbAsyncInit = function() {
FB.init({
xfbml : true,
version : 'v4.0'
});
};
(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = 'https://connect.facebook.net/en_US/sdk/xfbml.customerchat.js';
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>
<!-- Your customer chat code -->
<div class="fb-customerchat"
attribution=setup_tool
page_id="******"
theme_color="#0084ff">
</div>
产生二次副本。每次添加一行时,此操作都会返回前一个数据帧的副本以及新行。更好的方法是保留所有行的列表,然后在最后只进行最后一个串联。
concat
答案 2 :(得分:1)
我能够想到这一点,它似乎至少快了一个数量级:
df = pd.concat([p_data_df.loc[:, ['S', 'C #', 'Num']], log_df[log_df['MD'].isin(p_data_df['Mid-C'].values)]], sort=False, axis=1)