如何在IPython HTML显示Pandas数据帧的格式?

2024-04-25 04:52:01 发布

您现在位置:Python中文网/ 问答频道 /正文

如何格式化pandas数据帧的IPython html显示以便

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

我知道numpyset_printoptions的功能,我可以做到:

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

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

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

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))

Tags: 数据lambdaformatmapdfhtmlipythondisplay
3条回答

这个问题是很久以前提的。那时,熊猫还没有包括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

Result using pd.Styler


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

pd.options.display.float_format = lambda x: '{:,.0f}'.format(x) if x > 1e3 else '{:,.2f}'.format(x)

关于操作点2:

numbers have commas as thousands separator

pandas(从0.20.1开始)不允许以简单的方式重写默认整数格式。它在^{}(函数labmda)中硬编码:

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

我假设您真正需要的是如何重写所有整数的格式:replace(“monkey patch”)theIntArrayFormatter以打印由逗号分隔的数千个整数值,如下所示:

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

侧边

对于漂浮物,您不需要跳过这些环,因为它有一个configuration option

display.float_format: The callable should accept a floating point number and return a string with the desired format of the number. This is used in some places like SeriesFormatter. See core.format.EngFormatter for an example.

HTML接收自定义的HTML数据字符串。没有人禁止您为.dataframe类(由to_html方法添加到表中)传递带有自定义CSS样式的样式标记。

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

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

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

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'))

相关问题 更多 >