打印时指定 Pandas DataFrame 列之间的空格数 示例数据代码

问题描述

当您打印调用 DataFrame.to_string 的 Pandas DataFrame 时,它​​通常会在列之间插入至少 2 个空格。例如这段代码

import pandas as pd

df = pd.DataFrame( {
    "c1" : ("a","bb","ccc","dddd","eeeeee"),"c2" : (11,22,33,44,55),"a3235235235": [1,2,3,4,5]
} )
print(df)

输出

       c1  c2  a3235235235
0       a  11            1
1      bb  22            2
2     ccc  33            3
3    dddd  44            4
4  eeeeee  55            5

每列之间至少有 2 个空格。

我正在复制打印在控制台上的 DataFarames 并将其粘贴到文档中,但我收到了难以阅读的反馈:人们希望列之间有更多空间。

有标准的方法吗?

我在 DataFrame.to_stringpandas.set_option 中没有看到任何选项。

我已经进行了网络搜索,但没有找到答案。 This question 询问如何删除这 2 个空格,而 this question 询问为什么有时列之间只有 1 个空格而不是 2 个空格(我也看到过这个错误,希望有人回答这个问题)。

我的 hack 解决方案是定义一个函数,该函数将 DataFrame 的列转换为 str 类型,然后在每个元素前面加上一个指定空格数的字符串。

这段代码添加到上面的代码中)

def prependspacesToColumns(df: pd.DataFrame,n: int = 3):
    spaces = ' ' * n
    
    # ensure every column name has the leading spaces:
    if isinstance(df.columns,pd.MultiIndex):
        for i in range(df.columns.nlevels):
            levelNew = [spaces + str(s) for s in df.columns.levels[i]]
            df.columns.set_levels(levelNew,level = i,inplace = True)
    else:
        df.columns = spaces + df.columns
    
    # ensure every element has the leading spaces:
    df = df.astype(str)
    df = spaces + df
    
    return df

dfSp = prependspacesToColumns(df,3)
print(dfSp)

输出

          c1     c2    a3235235235
0          a     11              1
1         bb     22              2
2        ccc     33              3
3       dddd     44              4
4     eeeeee     55              5

这是想要的效果

但我认为熊猫肯定必须有一些内置简单的标准方法来做到这一点。我怎么错过了?

此外,该解决方案需要处理列是 MultiIndex 的 DataFrame。要继续代码示例,请考虑以下修改

idx = (("Outer","Inner1"),("Outer","Inner2"),"a3235235235"))
df.columns = pd.MultiIndex.from_tuples(idx)

解决方法

您可以通过formatters来完成此操作;创建字典 {'col_name': format_string} 需要一些代码。找到每列中的最大字符长度或列标题的长度,以较大者为准,添加一些填充,然后传递一个格式化字符串。

使用 partial 中的 functools 作为格式化程序期望一个参数函数,但我们需要为每一列指定不同的宽度。

示例数据

import pandas as pd
df = pd.DataFrame({"c1": ("a","bb","ccc","dddd",'eeeeee'),"c2": (1,22,33,44,55),"a3235235235": [1,2,3,4,5]})

代码

from functools import partial

# Formatting string 
def get_fmt_str(x,fill):
    return '{message: >{fill}}'.format(message=x,fill=fill)

# Max character length per column
s = df.astype(str).agg(lambda x: x.str.len()).max() 

pad = 6  # How many spaces between 
fmts = {}
for idx,c_len in s.iteritems():
    # Deal with MultIndex tuples or simple string labels. 
    if isinstance(idx,tuple):
        lab_len = max([len(str(x)) for x in idx])
    else:
        lab_len = len(str(idx))

    fill = max(lab_len,c_len) + pad - 1
    fmts[idx] = partial(get_fmt_str,fill=fill)

print(df.to_string(formatters=fmts))

            c1      c2      a3235235235
0            a      11                1
1           bb      22                2
2          ccc      33                3
3         dddd      44                4
4       eeeeee      55                5

# MultiIndex Output
         Outer                             
        Inner1      Inner2      a3235235235
0            a          11                1
1           bb          22                2
2          ccc          33                3
3         dddd          44                4
4       eeeeee          55                5