我想在IPython笔记本上写一篇论文,但是遇到了显示格式的一些问题。假设我有以下数据帧df
,有没有办法将var1
和var2
格式化为2位小数,var3
格式化为百分比。
var1 var2 var3
id
0 1.458315 1.500092 -0.005709
1 1.576704 1.608445 -0.005122
2 1.629253 1.652577 -0.004754
3 1.669331 1.685456 -0.003525
4 1.705139 1.712096 -0.003134
5 1.740447 1.741961 -0.001223
6 1.775980 1.770801 -0.001723
7 1.812037 1.799327 -0.002013
8 1.853130 1.822982 -0.001396
9 1.943985 1.868401 0.005732
里面的数字不会乘以100,例如-0.0057 = -0.57%。
使用round函数替换值,并格式化百分比数字的字符串表示形式:
df['var2'] = pd.Series([round(val, 2) for val in df['var2']], index = df.index)
df['var3'] = pd.Series(["{0:.2f}%".format(val * 100) for val in df['var3']], index = df.index)
round函数将浮点数舍入为函数的第二个参数提供的小数位数。
字符串格式允许您根据需要表示数字。您可以通过更改f
之前的数字来更改显示的小数位数。
附:我不确定你的'百分比'数字是否已经乘以100.如果他们已经清楚你会想要改变显示的小数位数,并删除百位乘法。
接受的答案建议修改原始数据以用于演示目的,这是您通常不想要的。想象一下,您需要使用这些列进行进一步分析,并且您需要通过舍入来丢失精度。
在您的情况下,您可以修改数据框中各列的格式:
output = df.to_string(formatters={
'var1': '{:,.2f}'.format,
'var2': '{:,.2f}'.format,
'var3': '{:,.2%}'.format
})
print(output)
为了您的信息'{:,.2%}'.format(0.214)
产生21.40%
,所以不需要乘以100。
你没有一个漂亮的HTML表格,只有一个文本表示。如果您需要继续使用HTML,请使用to_html
函数。
from IPython.core.display import display, HTML
output = df.to_html(formatters={
'var1': '{:,.2f}'.format,
'var2': '{:,.2f}'.format,
'var3': '{:,.2%}'.format
})
display(HTML(output))
更新
从熊猫0.17.1开始,生活变得更轻松,我们可以立即获得一个漂亮的html表:
df.style.format({
'var1': '{:,.2f}'.format,
'var2': '{:,.2f}'.format,
'var3': '{:,.2%}'.format,
})
您还可以设置float的默认格式:
pd.options.display.float_format = '{:.2f}%'.format
正如@linqu所建议的那样,您不应该更改您的数据以进行演示。由于pandas 0.17.1,(条件)格式化变得更容易。引用documentation:
您可以使用
DataFrame
属性应用条件格式,即DataFrame.style
的视觉样式,具体取决于其中的数据。这是一个返回pandas.Styler
对象的属性,该对象具有格式化和显示DataFrames
的有用方法。
对于你的例子,那将是(通常的表将显示在Jupyter中):
df.style.format({
'var1': '{:,.2f}'.format,
'var2': '{:,.2f}'.format,
'var3': '{:,.2%}'.format,
})
另一种方法是,您需要在更大范围的列上执行此操作
使用applymap
df[['var1','var2']] = df[['var1','var2']].applymap("{0:.2f}".format)
df['var3'] = df['var3'].applymap(lambda x: "{0:.2f}%".format(x*100))
如果需要在多列上应用函数,applymap非常有用;它本质上是这个具体例子的下面的缩写:
df[['var1','var2']].apply(lambda x: map(lambda x:'{:.2f}%'.format(x),x),axis=1)
下面适用的重要说明,地图applymap:
Difference between map, applymap and apply methods in Pandas
做就是了:
df.style.format({'var1': "{:.2f}",'var2': "{:.2f}",'var3': "{:.2%}"})
得到:
var1 var2 var3
id
0 1.46 1.50 -0.57%
1 1.58 1.61 -0.51%
2 1.63 1.65 -0.48%
3 1.67 1.69 -0.35%
4 1.71 1.71 -0.31%
5 1.74 1.74 -0.12%
6 1.78 1.77 -0.17%
7 1.81 1.80 -0.20%
8 1.85 1.82 -0.14%
9 1.94 1.87 0.57%
作为可接受的答案的类似方法,可以被认为更具可读性,优雅和通用(YMMV),您可以利用map
方法:
# OP example
df['var3'].map(lambda n: '{:,.2%}'.format(n))
# also works on a series
series_example.map(lambda n: '{:,.2%}'.format(n))
性能方面,这与OP解决方案非常接近(略慢)。
顺便说一句,如果你选择去pd.options.display.float_format
路线,考虑使用上下文管理器来处理每个parallel numpy example的状态。