【问题标题】:specify number of spaces between pandas DataFrame columns when printing打印时指定 pandas DataFrame 列之间的空格数
【发布时间】:2021-05-28 05:04:04
【问题描述】:

当您打印调用 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

这是想要的效果。

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

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

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

【问题讨论】:

    标签: python pandas dataframe tostring spaces


    【解决方案1】:

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

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

    样本数据

    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
    

    【讨论】:

    • 谢谢!我将您的回复标记为答案,因为您展示了一种深层的低级方法来实现任何所需的格式化效果,包括我对列间距的需求。我仍然认为 pandas 需要在 DataFrame.to_string 中添加某种选项...
    • 与我原来的 3 行 hack 解决方案相比,您的代码解决了一个缺陷:还需要考虑列名。我已经编辑了我的问题的 hack 代码来解决这个问题,并使用了您修改后的 DataFrame(其中包括一个长列名)。
    • 我注意到,但是,您的解决方案有一个小问题:列之间的间距不是恒定的!我在索引列和 c1 之间计算了 8 个空格,然后在其余两列之间计算了 7 个空格。相比之下,我修改后的 hack 代码在所有列之间产生相同数量的空格。
    • @HaroldFinch 很难说,但这可能是由于索引的格式(带有额外的空格)导致的问题,因此它与第一列的内容混为一谈。 IE。右边的索引垫,左边的列不好,所以第一列看起来很奇怪。 AFAIK,你不能格式化索引,所以你可以把它变成一列,格式化然后 to_string(index=False)。但它确实变得复杂。
    • 我刚刚发现我们的两个原始代码都不处理列类型为 pandas.MultiIndex 的 DataFrame。我的原始代码崩溃了,而你的代码太多了。我将编辑我的问题以处理 MultiIndex。
    猜你喜欢
    • 2018-10-10
    • 2022-11-25
    • 2020-01-15
    • 2015-12-30
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 2013-10-08
    相关资源
    最近更新 更多