【Python踩坑记录】

关于Python中DataFrame批量处理str时的bug:

把df数据从小数转化成百分数形式时,写出的一个bug,记录一下
当时觉得百思不得其解,现在想想,觉得:啊,我真是个...欸


问题描述

读取excel中的数据,返回值为DataFrame,对DataFrame中某一行进行操作,将小数转化为百分数
我写的代码是这样的:

# 读数据
df = pd.read_excel('data.xlsx')
# 小数转化为百分数形式,先 *100, 保留两位小数,然后转成 str, 加一个 %
df['rate'] = str(round(df['rate'] * 100, 2)) + "%"
# 存数据
df.to_csv('data_res.csv', index=False)

结果它返回是这样的:

# data.excel:
   index  price    rate
0     12    100  0.0012
1     43    150  0.0934
2     54    200  0.0003
3     32    324  0.0043
4     56    546  0.0234

# 返回结果
   index  price                                               rate
0     12    100  0    0.12\n1    9.34\n2    0.03\n3    0.43\n4 ...
1     43    150  0    0.12\n1    9.34\n2    0.03\n3    0.43\n4 ...
2     54    200  0    0.12\n1    9.34\n2    0.03\n3    0.43\n4 ...
3     32    324  0    0.12\n1    9.34\n2    0.03\n3    0.43\n4 ...
4     56    546  0    0.12\n1    9.34\n2    0.03\n3    0.43\n4 ...

反正看到结果的时候,我是挺震惊的。然后还因为存为CSV的文件过大,打开的时候把excel给卡死了一回,内心又稍微崩溃了几分钟


原因分析:

问题出在str()上,直接看代码吧

# 小数转化为百分数形式,先 *100, 保留两位小数,然后转成 str, 加一个 %
df['rate'] = str(round(df['rate'] * 100, 2)) + "%"

这行代码,我想的是:df的每一行批量操作,先每行*100,再每行转str,每行str再加个百分号
但是Python不这么想,它想的是:先每行 *100,然后全部的行转成str, 赋值给df[‘rate’]的每一行

也就是说,我希望的是类似这样的操作:

df['rate'] = df['rate'] * 100 # 每行按照相同逻辑批量操作

Python执行的是类似这样的操作:

df['rate'] = "反正就是一个str" # 每行赋值相同

解决方案:

法1: Lambda表达式批量操作
法2: str() 转为astype(str)

上代码:

# 1. Lambda表达式批量操作 因为本来就是对单行进行批量操作,所以str()里面是一行的数据,没问题
df['rate'] = df.apply(lambda x: str(round(x['rate'] * 100, 2)) + "%", axis=1)
# 2. str() 转为astype(str) 
# astype(str) 是 pandas 中的方法,专门用于将 DataFrame 或 Series 中的列数据转换为字符串类型
# 这里是转换整个 DataFrame
df['rate'] = round(df['rate'] * 100, 2).astype(str) + "%"

这回结果就正常了

   index  price   rate
0     12    100  0.12%
1     43    150  9.34%
2     54    200  0.03%
3     32    324  0.43%
4     56    546  2.34%

总结

对于写的这个bug,对于这个bug害我加班半小时,我的内心感到非常的平静和简单。

高频次地写Python快一个月了,有时觉得我和Python很熟了,但还是会偶发这种匪夷所思的问题(当然,这完全是我的错

有时候我会有一种:和Python很熟但偶尔会被反咬一口的感觉
哈哈哈(抹眼泪

总之这个bug更类似一个阅读理解的逻辑问题,我没有想清楚str()的用法,想当然就用了,结果当然是错的。但是这个bug, 在踩过坑之前,我是不会想的到和主动避免的。

只能说我还有很大的进步空间,嗯。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值