一、摘要

设置 DataFrame 中数据 有效位数的方法有很多,
可以用 pandas 中的 map, apply,applymap 方法,或者pandas style 中的 format方法,
也可以不使用DataFrame中的接口,而是用单独的 %.f 和 format格式化方法 或者 round 方法格式化数据。

本文主要对在做 display 自定义效数有效位数 等其他style 设置 实践中遇到的一些错误和学到的文章做一个总结。

二、 场景和需求:

  • 为 dataframe 中的数(数值)设置显示的小数位数。

  • 数据类型不固定(考虑有字符串,数值类型),数据不固定(有None, nan 和来自EXCEL 或者 formulas(可以解析excel公式的python第三方库)错误值 #VALUE! )

  • 设置完小数位数以后,还有其他 style 的链式操作。

    三、思路:

    3.1 判断数据是否是数值

    (包括 字符串数字)

判断方法:

这里学习了菜鸟教程里面一篇文章 Python 判断字符串是否为数字
里面不是单纯使用 isinstance(val, number.Number) 来判断是否是数值类型 (因为这里也需要字符串数字 比如’123’)。

具体方法如下:

  1. #对汉字表示的数字也可分辨
  2. def is_number(s):
  3. try: # 如果能运行float(s)语句,返回True(字符串s是浮点数)
  4. float(s)
  5. return True
  6. except ValueError: # ValueError为Python的一种标准异常,表示"传入无效的参数"
  7. pass # 如果引发了ValueError这种异常,不做任何事情(pass:不做任何事情,一般用做占位语句)
  8. try:
  9. import unicodedata # 处理ASCii码的包
  10. for i in s:
  11. unicodedata.numeric(i) # 把一个表示数字的字符串转换为浮点数返回的函数
  12. #return True
  13. return True
  14. except (TypeError, ValueError):
  15. pass
  16. return False

我这里没有过多考虑汉字表示的数字等,所以只用到了:

  1. def is_number(s):
  2. try: # 如果能运行float(s)语句,返回True(字符串s是浮点数)
  3. float(s)
  4. return True
  5. except ValueError: # ValueError为Python的一种标准异常,表示"传入无效的参数"
  6. pass # 如果引发了ValueError这种异常,不做任何事情(pass:不做任何事情,一般用做占位语句)

3.2 即便是数值类型, 其中也有 nan 这种数据

最后又添加了 是否是 nan 的判断, 这里有一篇教程 python中nan的比较, 是使用 val != val 判断的。

所以最终的判断是否是数字的代码如下:

  1. def is_valid_number(val):
  2. if val is None:
  3. return False
  4. if isinstance(val, Number):
  5. if val != val:
  6. return False
  7. return True
  8. try:
  9. float(val)
  10. return True
  11. except ValueError:
  12. return False

3.3 格式化数据设置有效位数

这里之前使用了很多办法,比如 :

3.3.1 在style 样式控制中进行格式化再链式调用其他样式控制。

pamdas.DataFrame.style.format (转自 Pandas Style 为数据表格美颜

  • 类似字符串

e.g. .format('{:.4f}')
但是这种办法一旦遇到 字符串类型数据 就报错了,当前还没有想到解决办法。

  • 使用 字典 格式化 特定 的列

e.g. df.style.format({'B': "{:0<4.0f}", 'D': '{:+.2f}'})

  • 使用 lambda 函数

e.g. df.style.format({"B": lambda x: "±{:.2f}".format(abs(x))})
直接报错,连浮点数都不能处理,当前还不知道是不是 style 链式调用的问题,还是 format 方法 不能传入 func 函数作为参数。(需要做记录再找下原因)

3.3.2 DataFrame.applymap重新获取一个已经格式化有效数字的 DataFrame, 再使用 df.style.applymap() 做其他格式化操作

DataFrame.applymap

(当前采用的这种办法, )
(
这里找了很多教程, 其中有用到的有 :
(1)Python浮点数控制小数精度 , 里面有个 round 函数。
但是这种办法,最后 display 显示的时候,会在 有效位 后 4 位后面,会多显示 2 个 0。
比如 2.123400

(2)python 浮点数指定位数
也是字符串格式方法,’%[width][.precision]f’ 这里要注意,格式化以后不再是 float, 而是 str 类型。

(3)python格式化中指定补零和整数浮点数的位数

  1. 4)[python输出指定位数小数](https://blog.csdn.net/u013925378/article/details/103383746)<br />**)**

我这里的办法是先获取一个新的 格式化好的DataFrame, 再做样式控制和 display。
代码里 先判断是否是数字, 然后先强转成 float (为了正常处理字符串类型的数字)。

  1. def format_significant_digits(val):
  2. if is_valid_number(val):
  3. return "{:.4f}".format(float(val))
  4. return val

最终使用 data_frame = data_frame.applymap(format_significant_digits) 获取格式化有效数字以后的新的 DataFrame, 注意,此时 DataFrame 中的数字 数据类型 已经是 字符串。

此后,再进行其他 sytle 的链式 样式控制 并 display 显示 不会再有上面提到的问题。


最后:

  1. 转载了很多原创作者的文章, 如果觉得有侵权 , 还请联系本人, 2627724977@qq.com
  2. 本文只是个人实践学习总结笔记,文章可能有很多疏漏和错误,以及很多可以优化的解决办法,还请随意评论指正探讨。