【问题标题】:How to format IPython html display of Pandas dataframe?如何格式化 Pandas 数据框的 IPython html 显示?
【发布时间】:2013-09-23 10:28:40
【问题描述】:

如何格式化熊猫数据帧的 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))

【问题讨论】:

  • 您还可以指定格式化程序列表,为不存在的那些使用 None 值 - 这简化了 frmt 创建:frmt = [frmt_map.get(dtype, None) for dtype in df.dtypes]。 +1 研究。

标签: python html pandas ipython


【解决方案1】:

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

所以最简单的解决方案是添加一个样式并将其与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'))

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

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

【讨论】:

  • 如果我们邮寄这个 html,在邮件中,HTML 的样式不正确,知道怎么做,很抱歉复活了非常老的线程。
  • 作为记录,我认为下面的@JulienMarrec 的new answer 现在应该被接受。
【解决方案2】:

这个问题是很久以前提出的。那时,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.options.display.float_format,而不是在子集列上调用.format

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

【讨论】:

  • 值得一提的是df.style.set_prop....render()会返回所需的html,而df.to_html则不会。
  • 有没有办法为各个列设置表格标题对齐方式?特别是将其设置为仅对具有右对齐内容的列进行右对齐?
  • 这是一个绝妙的例子,它不仅回答了问题,而且还展示了如何在 Pandas 中使用样式。我希望他们的医生有这样的东西。谢谢。
【解决方案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

一边

对于花车,你不需要跳过那些圈,因为它有一个configuration option

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-17
    • 2016-04-29
    • 1970-01-01
    • 2019-12-05
    • 1970-01-01
    • 2018-09-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多