向pandas DataFrame添加大量列的效率问题

一、问题背景

需要遍历文本,并将符合条件的数据写入DataFrame。

采用的方法是for循环结合if判断,并通过insert方法逐列添加,如下:

ctria3 = pd.DataFrame(index=['属性', '节点'])  # 创建一个空的DataFrame

for line in data:
    if line.startswith('CTRIA3'):
        line = line.strip('\n')  # 去除末尾的换行符
        e_id = line[c2]  # 单元编号
        p_id = line[c3]  # 单元属性编号
        nodes = [line[c4], line[c5], line[c6]]  # 单元的3个节点
        ctria3.insert(loc=0, column=e_id, value=[p_id, nodes])

这个方法效率非常低,在电脑上运行大概需要50秒,在笔记本上则跳出警告:

PerformanceWarning: DataFrame is highly fragmented. This is usually the result of calling `frame.insert` many times, which has poor performance

二、原因分析

当时猜测的原因有如下几个:

  1. for if 的效率问题;
  2. 字符串识别时,startswith函数的效率问题;
  3. dataframe添加列的方式,即insert方法的效率。

通过逐一排查:

  1. for if if 的方式修改为for if for if的方式,速度变化不大;
  2. 将startswith方法修改,即将line.startswith('CTRIA3') 修改为 line[:6] == 'CTRIA3', 速度略有提升,但还是很慢;
  3. 将insert方法替换,改为ctria3[e_id] = [p_id, nodes],速度不变,因为两者事实上都是insert方法。

三、解决方法

最后发现最主要拖慢速度的还是原因(3),参考该文(向Pandas DataFrame添加大量列的最佳实践)的建议,采用列表和pandas的concat方法修改,相比之前的方式速度提高了约5倍,只需不到10秒了,尽管还是比较慢,,但我已经很满意了。

修改后的代码如下:

dfs = []

for line in data:
    if line[:6] == 'CTRIA3':
        line = line.strip('\n')  # 去除末尾的换行符
        e_id = line[c2]  # 单元编号
        p_id = line[c3]  # 单元属性编号
        nodes = [line[c4], line[c5], line[c6]]  # 单元的3个节点
        dfs.append(DataFrame(columns=[e_id], data=[p_id, nodes]))
    ctria3 = concat(dfs, axis=1)
    ctria3.index = ['属性', '节点']

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值