如何使用格式字符串来显示浮点数列的pandas DataFrame?

278

我想使用 print() 和 IPython display() 来展示一个给定格式的 pandas dataframe。例如:

df = pd.DataFrame([123.4567, 234.5678, 345.6789, 456.7890],
                  index=['foo','bar','baz','quux'],
                  columns=['cost'])
print df

         cost
foo   123.4567
bar   234.5678
baz   345.6789
quux  456.7890

我希望以某种方式迫使它打印

         cost
foo   $123.46
bar   $234.57
baz   $345.68
quux  $456.79

如何做到这一点?无需修改数据本身或创建副本,只需更改其显示方式。


2
“cost”是唯一的浮点列吗?还有其他不应该用“$”格式化的浮点列吗? - unutbu
我只想针对成本列执行此操作(我的真实数据还有其他列)。 - Jason S
我意识到一旦$被附加,数据类型会自动变为对象。 - Nguai al
10个回答

450
import pandas as pd
pd.options.display.float_format = '${:,.2f}'.format
df = pd.DataFrame([123.4567, 234.5678, 345.6789, 456.7890],
                  index=['foo','bar','baz','quux'],
                  columns=['cost'])
print(df)
产生。
        cost
foo  $123.46
bar  $234.57
baz  $345.68
quux $456.79

但这仅适用于您希望对每个浮点数使用美元符号格式的情况。

否则,如果您只想对某些浮点数进行美元格式化,则需要预先修改数据框(将这些浮点数转换为字符串):

import pandas as pd
df = pd.DataFrame([123.4567, 234.5678, 345.6789, 456.7890],
                  index=['foo','bar','baz','quux'],
                  columns=['cost'])
df['foo'] = df['cost']
df['cost'] = df['cost'].map('${:,.2f}'.format)
print(df)
产出。
         cost       foo
foo   $123.46  123.4567
bar   $234.57  234.5678
baz   $345.68  345.6789
quux  $456.79  456.7890

5
截至 pandas 0.22 版本,这个解决方案对我仍然有效。 - Taylor D. Edmiston
53
如此示例如 这里所示,您可以通过使用 with pd.option_context('display.float_format', '${:,.2f}'.format'): 仅为给定块修改选项。 - Andre Holzner
9
@AndreHolzner 的注释中,在闭合括号之前多了一个 ',除此之外,它的功能非常好! - dTanMan
嘿 @unbunto。对你的解决方案赞一个。正是我在寻找的。当我使用openpyxl将df转储到Excel文件中时,我遇到了“数字存储为文本”的错误。你有任何想法如何避免这个问题吗? - goidelg
如果你想使用f-strings,那么列表推导式可以很好地工作:df['cost'] = [f"${x:.2f}" for x in df['cost']] - Colin
显示剩余2条评论

94

如果您不想修改数据框,可以为该列使用自定义格式化程序。

import pandas as pd
pd.options.display.float_format = '${:,.2f}'.format
df = pd.DataFrame([123.4567, 234.5678, 345.6789, 456.7890],
                  index=['foo','bar','baz','quux'],
                  columns=['cost'])


print df.to_string(formatters={'cost':'${:,.2f}'.format})
产量。
        cost
foo  $123.46
bar  $234.57
baz  $345.68
quux $456.79

3
格式化程序是否可以在多级列上工作? - user2579685
4
据我所知,这个例子在没有第二行代码pd.options.display.float_format = '${:,.2f}'.format的情况下也可以正常工作。 - pianoJames

83

从Pandas 0.17版本开始,现在有一个样式系统,它基本上使用Python格式字符串为DataFrame提供了格式化的视图:

import pandas as pd
import numpy as np

constants = pd.DataFrame(
    [('pi', np.pi), ('e', np.e)],
    columns=['name', 'value'])
C = constants.style.format({'name':'~~ {} ~~', 'value':'--> {:15.10f} <--'})
C

显示

table showing formatted values

这是一个视图对象;DataFrame本身不会改变格式,但在DataFrame中的更新会反映在视图中。
constants.name = ['pie', 'eek']
C

table showing updated values

然而,它似乎有一些限制:
  • 在原地添加新行和/或列似乎会导致样式视图不一致(不会添加行/列标签):

    constants.loc[2] = dict(name='bogus', value=123.456)
    constants['comment'] = ['fee', 'fie', 'fo']
    constants
    

    显示新行和列中未格式化值的表格

    看起来还好,但是:

    C
    

    显示格式问题(对齐错误,未格式化值)的表格

  • 格式化仅适用于值,而不适用于索引条目:

    constants = pd.DataFrame(
        [('pi', np.pi), ('e', np.e)],
        columns=['name', 'value']
        ).set_index('name')
    C = constants.style.format({'name':'~~ {} ~~', 'value':'--> {:15.10f} <--'})
    C
    

    显示格式化值但未格式化索引的表格


2
我可以在解释器中使用DataFrame.style吗? - Jms
format_index 是在 Pandas 1.4.0 版本中新增的。 - wjandrea
截至Pandas 2.0.1版本,新的行/列标签已经正确添加,但值仍然保持未格式化状态。 - wjandrea

43
与上面的unutbu类似,您也可以使用applymap如下:
import pandas as pd
df = pd.DataFrame([123.4567, 234.5678, 345.6789, 456.7890],
                  index=['foo','bar','baz','quux'],
                  columns=['cost'])

df = df.applymap("${0:.2f}".format)

我喜欢在调用 df.to_csv() 之前使用这种方法,以确保我的 .csv 文件中的所有列具有相同的“数字宽度”。谢谢! - jeschwar

18
如果您不想永久更改显示格式,并且可能稍后应用新的格式,我个人比较喜欢使用资源管理器(Python中的with语句)。在您的情况下,您可以这样做:

如果您不希望永久更改显示格式,并且可能稍后应用新的格式,我个人更喜欢使用资源管理器(Python中的with语句)。在您的情况下,您可以这样做:

with pd.option_context('display.float_format', '${:0.2f}'.format):
   print(df)
如果在您的代码中需要不同格式,只需在上面片段中仅更改格式即可。

11

我喜欢使用pandas.apply()结合python format()。

import pandas as pd
s = pd.Series([1.357, 1.489, 2.333333])

make_float = lambda x: "${:,.2f}".format(x)
s.apply(make_float)

此外,它可以轻松地与多列一起使用...

df = pd.concat([s, s * 2], axis=1)

make_floats = lambda row: "${:,.2f}, ${:,.3f}".format(row[0], row[1])
df.apply(make_floats, axis=1)

11

不要干涉 pd.options 并全局地影响数据框的渲染,你可以使用 DataFrame.style.format,仅对一个数据框进行渲染样式。

df.style.format({
  'cost': lambda val: f'${val:,.2f}',
})

>>>
>>>            cost
>>> ---------------
>>> foo   $123.4567
>>> bar   $234.5678
>>> baz   $345.6789
>>> quux   $456.789

说明

df.style.format函数接受一个字典,其键将映射到您想要样式化的列名,而值是一个可调用对象,该对象接收指定列的每个值,并必须返回表示格式化值的字符串。这仅影响数据帧的渲染,不会更改底层数据。


1
df.style 创建了一个 HTML 表格,但在打印到文本界面时不太美观。 - user511

5

现在,我偏向于使用上下文管理器来显示数据框:

with pd.option_context('display.float_format', '${:,.2f}'.format):
    display(df)

该格式仅用于显示此数据帧


4

您还可以将区域设置为所在地,并将float_format设置为使用货币格式。这将自动在美国货币中设置$符号。

import locale

locale.setlocale(locale.LC_ALL, "en_US.UTF-8")

pd.set_option("float_format", locale.currency)

df = pd.DataFrame(
    [123.4567, 234.5678, 345.6789, 456.7890],
    index=["foo", "bar", "baz", "quux"],
    columns=["cost"],
)
print(df)

        cost
foo  $123.46
bar  $234.57
baz  $345.68
quux $456.79

2

summary:


    df = pd.DataFrame({'money': [100.456, 200.789], 'share': ['100,000', '200,000']})
    print(df)
    print(df.to_string(formatters={'money': '${:,.2f}'.format}))
    for col_name in ('share',):
        df[col_name] = df[col_name].map(lambda p: int(p.replace(',', '')))
    print(df)
    """
        money    share
    0  100.456  100,000
    1  200.789  200,000

        money    share
    0 $100.46  100,000
    1 $200.79  200,000

         money   share
    0  100.456  100000
    1  200.789  200000
    """

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接