Seaborn:有没有更好的方法将文本包装在我的条形图中?
Seaborn: Is there a better way to wrap the text in my bar plot?
我正在为条形图编写一个函数,遇到了另一个小问题。我有一些太长的 ytick 标签,导致无法看到我的 y 轴标签。当我大幅减小 ytick 标签的大小时,我只能看到 y 标签。
def bar_plot(data, x, y, title):
sns.set_style('darkgrid')
data = data.sort_values(ascending=False, by=x)
data = data.head(n=10)
if (data[x]>1000000).any():
data[x] = data[x] / 1000000
ax = sns.barplot(data=data, x=x, y=y)
ax.set_title(title, size=35)
ax.set_xlabel(x + ' ($ Millions)', size=15)
ax.set_ylabel(y, size=15)
ax.set_yticklabels(data[y].head(n=10), wrap=True)
else:
ax = sns.barplot(data=data, x=x, y=y)
ax.set_xlabel(x, size=15)
ax.set_ylabel(y, size=15)
ax.set_title(title, size=35)
ax.set_yticklabels(data[y].head(n=10), wrap=True)
我已经尝试 ax.set_yticklabels(data[y].head(n=10), wrap=True)
将文本换行。虽然它有效,但它没有足够地包装文本。有没有办法告诉 wrap=True
在 x 个字符后换行?我试过用谷歌搜索这个但找不到任何有用的东西。
编辑
我正在使用的数据框格式类似于
Client Name Col 1 Col 2 Col 3 Col 4 Col 5
Some name 51,235.00 nan 23,423.00 12,456.00 654.00
Some long company name 152.00 5,626.00 nan 82,389.00 5,234.00
Name 12,554.00 5,850.00 1,510.00 nan 12,455.00
Company 12,464.00 nan 752.00 1,243.00 1,256.00
Long Company Name 12,434.00 78,915.00 522.00 2,451.00 6,567.00
作为@ImportanceOfBeingErnest pointed out, you can use the textwrap
module to do this, specifically useful would be textwrap.fill()
:
textwrap.fill(text[, width[, ...]])
Wraps the single paragraph in text so every line is at most width
characters long, and returns a single string containing the wrapped paragraph. fill()
is shorthand for
"\n".join(wrap(text, ...))
尽管您需要在每个标签上单独调用它,例如
ax.set_yticklabels([textwrap.fill(e, width) for e in data[y].head()])
编辑
这里有一个更完整的例子来展示用法:
import textwrap
import matplotlib.pyplot as plt
import pandas as pd
df = {'Client Name': ['Some Name', 'Some long company name', 'Name',
'Company', 'Long Comany Name'],
'Col 1': [51235, 152, 12554, 12464, 12434]}
data = pd.DataFrame(df)
fig, ax = plt.subplots(1)
ax.set_yticklabels(data['Client Name'].head())
plt.show()
这将显示以下内容
而
ax.set_yticklabels([textwrap.fill(e, 7) for e in data['Client Name'].head()])
plt.show()
会显示更像
的内容
textwrap
看起来很容易使用,但它会按预定的字符数拆分句子。这是一个每 n
个单词插入一个换行符 (\n
) 的函数。然后,您可以使用 out
作为标签 x-(或 y-)轴刻度线。避免任何不必要的包依赖也是明智的。
Lst = ['You can never understand one language until you understand at least two.',
'Language is the blood of the soul into which thoughts run and out of which they grow.']
InsertNewlines = lambda lst, n=2: '\n'.join([' '.join(lst[i:i + n]) for i in range(0, len(lst), n)]) # n=words to keep together
out = [InsertNewlines(s.split()) for s in Lst]
输出:
['You can\nnever understand\none language\nuntil you\nunderstand at\nleast two.',
'Language is\nthe blood\nof the\nsoul into\nwhich thoughts\nrun and\nout of\nwhich they\ngrow.']
来自William Miller的回答:
最好改一下这部分:
ax.set_yticklabels([textwrap.fill(e, 7) for e in data['Client Name'].head()])
plt.show()
您应该将其更改为:
ax.set_yticklabels([textwrap.fill(e, 7) for e in data['Client Name']])
plt.show()
其次确保导入 textwrap
我正在为条形图编写一个函数,遇到了另一个小问题。我有一些太长的 ytick 标签,导致无法看到我的 y 轴标签。当我大幅减小 ytick 标签的大小时,我只能看到 y 标签。
def bar_plot(data, x, y, title):
sns.set_style('darkgrid')
data = data.sort_values(ascending=False, by=x)
data = data.head(n=10)
if (data[x]>1000000).any():
data[x] = data[x] / 1000000
ax = sns.barplot(data=data, x=x, y=y)
ax.set_title(title, size=35)
ax.set_xlabel(x + ' ($ Millions)', size=15)
ax.set_ylabel(y, size=15)
ax.set_yticklabels(data[y].head(n=10), wrap=True)
else:
ax = sns.barplot(data=data, x=x, y=y)
ax.set_xlabel(x, size=15)
ax.set_ylabel(y, size=15)
ax.set_title(title, size=35)
ax.set_yticklabels(data[y].head(n=10), wrap=True)
我已经尝试 ax.set_yticklabels(data[y].head(n=10), wrap=True)
将文本换行。虽然它有效,但它没有足够地包装文本。有没有办法告诉 wrap=True
在 x 个字符后换行?我试过用谷歌搜索这个但找不到任何有用的东西。
编辑
我正在使用的数据框格式类似于
Client Name Col 1 Col 2 Col 3 Col 4 Col 5
Some name 51,235.00 nan 23,423.00 12,456.00 654.00
Some long company name 152.00 5,626.00 nan 82,389.00 5,234.00
Name 12,554.00 5,850.00 1,510.00 nan 12,455.00
Company 12,464.00 nan 752.00 1,243.00 1,256.00
Long Company Name 12,434.00 78,915.00 522.00 2,451.00 6,567.00
作为@ImportanceOfBeingErnest pointed out, you can use the textwrap
module to do this, specifically useful would be textwrap.fill()
:
textwrap.fill(text[, width[, ...]])
Wraps the single paragraph in text so every line is at most
width
characters long, and returns a single string containing the wrapped paragraph.fill()
is shorthand for
"\n".join(wrap(text, ...))
尽管您需要在每个标签上单独调用它,例如
ax.set_yticklabels([textwrap.fill(e, width) for e in data[y].head()])
编辑
这里有一个更完整的例子来展示用法:
import textwrap
import matplotlib.pyplot as plt
import pandas as pd
df = {'Client Name': ['Some Name', 'Some long company name', 'Name',
'Company', 'Long Comany Name'],
'Col 1': [51235, 152, 12554, 12464, 12434]}
data = pd.DataFrame(df)
fig, ax = plt.subplots(1)
ax.set_yticklabels(data['Client Name'].head())
plt.show()
这将显示以下内容
而
ax.set_yticklabels([textwrap.fill(e, 7) for e in data['Client Name'].head()])
plt.show()
会显示更像
的内容textwrap
看起来很容易使用,但它会按预定的字符数拆分句子。这是一个每 n
个单词插入一个换行符 (\n
) 的函数。然后,您可以使用 out
作为标签 x-(或 y-)轴刻度线。避免任何不必要的包依赖也是明智的。
Lst = ['You can never understand one language until you understand at least two.',
'Language is the blood of the soul into which thoughts run and out of which they grow.']
InsertNewlines = lambda lst, n=2: '\n'.join([' '.join(lst[i:i + n]) for i in range(0, len(lst), n)]) # n=words to keep together
out = [InsertNewlines(s.split()) for s in Lst]
输出:
['You can\nnever understand\none language\nuntil you\nunderstand at\nleast two.',
'Language is\nthe blood\nof the\nsoul into\nwhich thoughts\nrun and\nout of\nwhich they\ngrow.']
来自William Miller的回答:
最好改一下这部分:
ax.set_yticklabels([textwrap.fill(e, 7) for e in data['Client Name'].head()])
plt.show()
您应该将其更改为:
ax.set_yticklabels([textwrap.fill(e, 7) for e in data['Client Name']])
plt.show()
其次确保导入 textwrap