Python 熊猫显示:截断列显示而不是换行

Python 熊猫显示:截断列显示而不是换行,python,pandas,jupyter-console,Python,Pandas,Jupyter Console,对于冗长的列名,无论设置什么,数据帧都将以非常混乱的形式显示 信息:我在Jupyter QtConsole,pandas 0.20.1中,在启动时指定了以下相关选项: pd.set_option('display.max_colwidth', 20) pd.set_option('expand_frame_repr', False) pd.set_option('display.max_rows', 25) 问题:如果需要,我如何截断数据帧,而不是将列包装到下一行,同时保持expand\u f

对于冗长的列名,无论设置什么,数据帧都将以非常混乱的形式显示

信息:我在Jupyter QtConsole,pandas 0.20.1中,在启动时指定了以下相关选项:

pd.set_option('display.max_colwidth', 20)
pd.set_option('expand_frame_repr', False)
pd.set_option('display.max_rows', 25)
问题:如果需要,我如何截断数据帧,而不是将列包装到下一行,同时保持
expand\u frame\u repr=False

这里有一个例子。同样,问题不取决于列的数量,而取决于列的长度

这不会导致以下问题:

df = pd.DataFrame(np.random.randn(1000, 1000),
                  columns=['col' + str(i) for i in range(1000)])
因为输出完全可读,看起来像:

具有长列名的相同数据帧导致了我所说的问题:

df = pd.DataFrame(np.random.randn(1000, 1000),
                  columns=['very_long_col_name_' 
                           + str(i) for i in range(1000)])


有没有办法使第二个输出与我缺少的第一个输出一致?(通过指定选项,而不是每次要查看时都使用
.iloc

使用
max\u列

from string import ascii_letters

df = pd.DataFrame(np.random.randint(10, size=(5, 52)), columns=list(ascii_letters))

with pd.option_context(
    'display.max_colwidth', 20,
    'expand_frame_repr', False,
    'display.max_rows', 25,
    'display.max_columns', 5,
):
    print(df.add_prefix('really_long_column_name_'))

   really_long_column_name_a  really_long_column_name_b            ...              really_long_column_name_Y  really_long_column_name_Z
0                    8                          1                  ...                                1                          9      
1                    8                          5                  ...                                2                          1      
2                    5                          0                  ...                                9                          9      
3                    6                          8                  ...                                0                          9      
4                    1                          2                  ...                                7                          1      

[5 rows x 52 columns]

另一个想法。。。显然不是你想要的,但也许你可以根据自己的需要改变它

d1 = df.add_suffix('_really_long_column_name')

with pd.option_context('display.max_colwidth', 4, 'expand_frame_repr', False):
    mw = pd.get_option('display.max_colwidth')
    print(d1.rename(columns=lambda x: x[:mw-3] + '...' if len(x) > mw else x))

   a...  b...  c...  d...  e...  f...  g...  h...  i...  j...  ...   Q...  R...  S...  T...  U...  V...  W...  X...  Y...  Z...
0    6     5     5     5     8     3     5     0     7     6   ...     9     0     6     9     6     8     4     0     6     7 
1    0     5     4     7     2     5     4     3     8     7   ...     8     1     5     3     5     9     4     5     5     3 
2    7     2     1     6     5     1     0     1     3     1   ...     6     7     0     9     9     5     2     8     2     2 
3    1     8     7     1     4     5     5     8     8     3   ...     3     6     5     7     1     0     8     1     4     0 
4    7     5     6     2     4     9     7     9     0     5   ...     6     8     1     6     3     5     4     2     3     2 

看起来它需要增强。
repr
功能中的相关代码如下:

    max_rows = get_option("display.max_rows")
    max_cols = get_option("display.max_columns")
    show_dimensions = get_option("display.show_dimensions")
    if get_option("display.expand_frame_repr"):
        width, _ = console.get_console_size()
    else:
        width = None
    self.to_string(buf=buf, max_rows=max_rows, max_cols=max_cols,
                   line_width=width, show_dimensions=show_dimensions)
因此,要么通过
expand\u frame\u repr=True
,它将换行;要么通过
expand\u frame\u repr=False
,它不应该换行。但代码中似乎有一个bug(应该是0.20.3 iirc):

pd.io.formats.format.DataFrameFormatter
中:

def _chk_truncate(self):
    """
    Checks whether the frame should be truncated. If so, slices
    the frame up.
    """
    from pandas.core.reshape.concat import concat

    # Column of which first element is used to determine width of a dot col
    self.tr_size_col = -1

    # Cut the data to the information actually printed
    max_cols = self.max_cols
    max_rows = self.max_rows

    if max_cols == 0 or max_rows == 0:  # assume we are in the terminal
                                        # (why else = 0)
        (w, h) = get_terminal_size()
        self.w = w
        self.h = h
        if self.max_rows == 0:
            dot_row = 1
            prompt_row = 1
            if self.show_dimensions:
                show_dimension_rows = 3
            n_add_rows = (self.header + dot_row + show_dimension_rows +
                          prompt_row)
            # rows available to fill with actual data
            max_rows_adj = self.h - n_add_rows
            self.max_rows_adj = max_rows_adj

        # Format only rows and columns that could potentially fit the
        # screen
        if max_cols == 0 and len(self.frame.columns) > w:
            max_cols = w
        if max_rows == 0 and len(self.frame) > h:
            max_rows = h
看起来它是想做你想做的,但是没有完成。它是根据列数而不是列的总宽度来检查
max\u cols


因此,您可以创建一个
show_df
函数,该函数将计算正确的列数,并在
选项_上下文中显示它,如pi2Squared的答案,或者在此处修复它(如果需要分发它,可能会提交一个补丁)。

正如其他人所指出的,熊猫本身似乎有缺陷或设计不好,因此,需要一种变通方法

由于数字相对较短,大多数情况下,这个问题都发生在数字列上。如果列标题中有空格,Pandas会将其拆分为多行,因此在显示数据帧时,您可以通过在数字列的列标题中插入空格来“侵入”正确的行为。我有一个单行程序来执行此操作:

def colfix(df, L=5): return df.rename(columns=lambda x: ' '.join(x.replace('_', ' ')[i:i+L] for i in range(0,len(x),L)) if df[x].dtype in ['float64','int64'] else x )
显示您的数据帧,只需键入

colfix(your_df)
请注意,重命名不会永久更改数据帧,它只会在名称中添加空格,以便一次显示数据帧

结果(在Jupyter笔记本中):

使用
colfix

没有:


嗯,这在Ipython3上不是问题。列被一个
/
拆分,随后的列被移到第一组下面。
pd.options.display.linew\u width
为您提供了什么?如果它是正确的,它通常看起来不错,但在一些不能自动计算它的控制台(qtconsole就像这个IIRC)中,它显示为无,在这种情况下,事情并不总是看起来很好…@Coldspeed我猜你有
expand\u frame\u repr=True
。我想避免这种说法。检查您的
pd.options.display.expand\u frame\u repr
@Corley 80。还有就是现在的
pd.options.display.width。。。我没有尝试过使用
expand\u frame\u repr
,即使在普通控制台中也很糟糕。谢谢,但我想看看是否还有其他解决方案。这将需要设置
pd.option\u context
,每次我想要打印这种类型的长列数据帧,否?。(否则,如果直接设置选项而没有上下文,则更漂亮的数据帧将被不必要地截断。绝对……如果您感兴趣,我可以炮制另一种不会改变选项的解决方案。是否需要显示整个列名?好问题……我对这两者都持开放态度,但倾向于选择截断的列名。)在colwidth,我已经设置了选项。是的,我就是这样thinking@BradSolomon更新帖子