如何在Pandas DataFrame的to_string输出中换行长列名?
考虑这个例子:
import pandas as pd
df = pd.DataFrame({
"LIDSA": [0, 1, 2, 3],
"CAE": [3, 5, 7, 9],
"FILA": [1, 2, 3, 4], # 2 is default, so table idx 1 is default
"VUAMA": [0.5, 1.0, 1.5, 2.0],
})
df_colnames = { # https://stackoverflow.com/q/48243818
"LIDSA": "Lorem ipsum dolor sit amet",
"CAE": "Consectetur adipiscing elit",
"FILA": "Fusce imperdiet libero arcu",
"VUAMA": "Vitae ultricies augue molestie ac",
}
# "Pandas autodetects the size of your terminal window if you set pd.options.display.width = 0" https://stackoverflow.com/q/11707586
with pd.option_context('display.max_rows', None, 'display.max_columns', None, 'display.width', 0, 'max_colwidth', 20, 'display.float_format', "{:.2f}".format):
df_str = df.rename(df_colnames,axis=1).to_string()
print(df_str)
这段代码在终端输出时,显示的宽度是111个字符:
Lorem ipsum dolor sit amet Consectetur adipiscing elit Fusce imperdiet libero arcu Vitae ultricies augue
molestie ac
0 0 3 1
0.50
1 1 5 2
1.00
2 2 7 3
1.50
3 3 9 4
2.00
结果是,只有最后一列的内容被换行了(相应的值也跟着换行)。我希望每个长的列名在大约20个字符的时候就换行,这样输出的值也能对应换行,像这样:
Lorem ipsum dolor Consectetur Fusce imperdiet Vitae ultricies
sit amet adipiscing elit libero arcu augue molestie ac
0 0 3 1 0.50
1 1 5 2 1.00
2 2 7 3 1.50
3 3 9 4 2.00
我原以为设置 'max_colwidth', 20
就能实现这个效果,但显然没有。
我甚至尝试在长列名中添加明确的换行符,但它们只显示为 \n
,列名还是在一行里(这在Pandas列名中的换行中也有提到)。
那么,在Pandas中,是否有办法让长列名在输出为普通文本字符串时“自动换行”呢?
2 个回答
1
Pandas这个库没有提供一个简单的方法来自动换行或分行显示长列名。当你把一个数据表(DataFrame)转换成字符串时,设置叫做max_colwidth的选项只影响表格里的数据,而不影响列标题。如果你尝试在列名中添加换行符,你会发现它并没有改变标题的显示方式;相反,你会在输出中看到"\n"这样的字符,这显然不是你想要的效果。
如果想让列名换行显示,你需要自己动手,稍微想一些办法。具体步骤是:
1. 写一个函数,这个函数可以把长列名分成几个小部分,每部分要足够短(比如,不超过20个字符),这样就能单独放在一行上。
2. 用这个函数处理所有的列名,然后调整你的数据表显示方式,让这些多行的列名看起来正常。
这个方法需要你手动修改列名,在你想换行的地方加上换行符,然后确保数据表的字符串表示(也就是你打印出来的内容)能正确显示这些换行。这主要是为了在你实际打印或展示数据表之前,先准备好数据和显示设置。
import pandas as pd
# Original DataFrame
df = pd.DataFrame({
"LIDSA": [0, 1, 2, 3],
"CAE": [3, 5, 7, 9],
"FILA": [1, 2, 3, 4],
"VUAMA": [0.5, 1.0, 1.5, 2.0],
})
# Dictionary with long column names
df_colnames = {
"LIDSA": "Lorem ipsum dolor sit amet",
"CAE": "Consectetur adipiscing elit",
"FILA": "Fusce imperdiet libero arcu",
"VUAMA": "Vitae ultricies augue molestie ac",
}
# Custom function to word-wrap text
def word_wrap(text, max_width):
"""
Word-wrap text at a specified width. Attempts to break lines at word boundaries
where possible.
"""
words = text.split()
lines = []
current_line = []
current_length = 0
for word in words:
if current_length + len(word) <= max_width:
current_line.append(word)
current_length += len(word) + 1 # +1 for space
else:
lines.append(' '.join(current_line))
current_line = [word]
current_length = len(word) + 1
lines.append(' '.join(current_line)) # Add the last line
return '\n'.join(lines)
# Apply word-wrap to column names
wrapped_colnames = {col: word_wrap(name, 20) for col, name in df_colnames.items()}
# Rename DataFrame columns
df = df.rename(columns=wrapped_colnames)
# Print the DataFrame with modified display settings
with pd.option_context('display.max_rows', None, 'display.max_columns', None, 'display.width', 0, 'max_colwidth', 20, 'display.float_format', "{:.2f}".format):
print(df.to_string())
5
你可以使用 textwrap.wrap
和 tabulate
来实现这个功能:
# pip install tabulate
from textwrap import wrap
from tabulate import tabulate
df_colnames_wrap = {k: '\n'.join(wrap(v, 20))
for k,v in df_colnames.items()}
print(tabulate(df.rename(columns=df_colnames_wrap),
headers='keys', tablefmt='plain'))
输出结果:
Lorem ipsum dolor Consectetur Fusce imperdiet Vitae ultricies
sit amet adipiscing elit libero arcu augue molestie ac
0 0 3 1 0.5
1 1 5 2 1
2 2 7 3 1.5
3 3 9 4 2
使用浮点数格式化:
print(tabulate(df.rename(columns=df_colnames_wrap)
.convert_dtypes(),
headers='keys', tablefmt='plain',
floatfmt='.2f'
))
输出结果:
Lorem ipsum dolor Consectetur Fusce imperdiet Vitae ultricies
sit amet adipiscing elit libero arcu augue molestie ac
0 0 3 1 0.50
1 1 5 2 1.00
2 2 7 3 1.50
3 3 9 4 2.00