34

如何格式化熊猫数据框的 IPython html 显示,以便

  1. 数字是正确的
  2. 数字有逗号作为千位分隔符
  3. 大浮点数没有小数位

我知道这numpyset_printoptions我可以做的设施:

int_frmt:lambda x : '{:,}'.format(x)
np.set_printoptions(formatter={'int_kind':int_frmt})

对于其他数据类型也是如此。

但是 IPython 在 html 中显示数据帧时不会选择这些格式选项。我还需要拥有

pd.set_option('display.notebook_repr_html', True)

但是上面有 1, 2, 3。

编辑:下面是我对 2 和 3 的解决方案(不确定这是最好的方法),但我仍然需要弄清楚如何使数字列正确对齐。

from IPython.display import HTML
int_frmt = lambda x: '{:,}'.format(x)
float_frmt = lambda x: '{:,.0f}'.format(x) if x > 1e3 else '{:,.2f}'.format(x)
frmt_map = {np.dtype('int64'):int_frmt, np.dtype('float64'):float_frmt}
frmt = {col:frmt_map[df.dtypes[col]] for col in df.columns if df.dtypes[col] in frmt_map.keys()}
HTML(df.to_html(formatters=frmt))
4

3 回答 3

25

HTML 接收自定义的 html 数据字符串。没有人禁止您传入带有自定义 CSS 样式的样式标签.dataframe(该to_html方法将其添加到表格中)。

所以最简单的解决方案是添加一个样式并将其与以下输出连接df.to_html

style = '<style>.dataframe td { text-align: right; }</style>'
HTML( style + df.to_html( formatters=frmt ) )

但我建议为 DataFrame 定义一个自定义类,因为这会改变笔记本中所有表格的样式(样式为“全局”)。

style = '<style>.right_aligned_df td { text-align: right; }</style>'
HTML(style + df.to_html(formatters=frmt, classes='right_aligned_df'))

您还可以在前面的单元格中定义样式,然后只需设置方法的classes参数to_html

# Some cell at the begining of the notebook
In [2]: HTML('''<style>
                    .right_aligned_df td { text-align: right; }
                    .left_aligned_df td { text-align: right; }
                    .pink_df { background-color: pink; }
                </style>''')

...

# Much later in your notebook
In [66]: HTML(df.to_html(classes='pink_df'))
于 2013-09-18T17:08:39.047 回答
19

这个问题很久以前就被问过了。那时,pandas 还没有包含pd.Styler。它是在版本中添加的0.17.1

以下是您将如何使用它来实现您想要的目标以及更多:

  • 将标题居中
  • 右对齐任意数字列
  • 左对齐其他列。
  • 为您想要的数字列添加格式化程序
  • 使每列具有相同的宽度。

以下是一些示例数据:

In [1]:
df = pd.DataFrame(np.random.rand(10,3)*2000, columns=['A','B','C'])
df['D'] = np.random.randint(0,10000,size=10)
df['TextCol'] = np.random.choice(['a','b','c'], 10)
df.dtypes

Out[1]:
A          float64
B          float64
C          float64
D            int64
TextCol     object
dtype: object

让我们使用以下格式对其进行格式化df.style

# Construct a mask of which columns are numeric
numeric_col_mask = df.dtypes.apply(lambda d: issubclass(np.dtype(d).type, np.number))

# Dict used to center the table headers
d = dict(selector="th",
    props=[('text-align', 'center')])

# Style
df.style.set_properties(subset=df.columns[numeric_col_mask], # right-align the numeric columns and set their width
                        **{'width':'10em', 'text-align':'right'})\
        .set_properties(subset=df.columns[~numeric_col_mask], # left-align the non-numeric columns and set their width
                        **{'width':'10em', 'text-align':'left'})\
        .format(lambda x: '{:,.0f}'.format(x) if x > 1e3 else '{:,.2f}'.format(x), # format the numeric values
                subset=pd.IndexSlice[:,df.columns[numeric_col_mask]])\
        .set_table_styles([d]) # center the header

使用 pd.Styler 的结果


请注意.format,您可以很好地设置全局默认值,而不是调用子集列pd.options.display.float_format

pd.options.display.float_format = lambda x: '{:,.0f}'.format(x) if x > 1e3 else '{:,.2f}'.format(x)
于 2016-12-06T10:31:00.780 回答
3

关于OP的第2点:

数字有逗号作为千位分隔符

pandas(从 0.20.1 开始)不允许以简单的方式覆盖默认整数格式。它被硬编码在pandas.io.formats.format.IntArrayFormatterlabmda函数)中:

class IntArrayFormatter(GenericArrayFormatter):

    def _format_strings(self):
        formatter = self.formatter or (lambda x: '% d' % x)
        fmt_values = [formatter(x) for x in self.values]
        return fmt_values

我假设您实际上要求的是如何覆盖所有整数的格式:替换(“猴子补丁”)IntArrayFormatter以用逗号分隔的千位打印整数值,如下所示:

import pandas

class _IntArrayFormatter(pandas.io.formats.format.GenericArrayFormatter):

    def _format_strings(self):
        formatter = self.formatter or (lambda x: ' {:,}'.format(x))
        fmt_values = [formatter(x) for x in self.values]
        return fmt_values

pandas.io.formats.format.IntArrayFormatter = _IntArrayFormatter

笔记:

  • 在 0.20.0 之前,格式化程序位于pandas.formats.format.
  • 在 0.18.1 之前,格式化程序位于pandas.core.format.

在旁边

对于浮动,您不需要跳过这些箍,因为它有一个配置选项

display.float_format:可调用对象应接受浮点数并返回具有所需数字格式的字符串。这在某些地方使用,例如SeriesFormatter. 参见core.format.EngFormatter示例。

于 2015-09-28T11:23:02.433 回答