我正在尝试格式化IPython笔记本中的输出。我尝试使用to_string函数,这巧妙地让我删除了索引列。但文本数据是正确的。
在[10]中:
import pandas as pd
columns = ['Text', 'Value']
a = pd.DataFrame ({'Text': ['abcdef', 'x'], 'Value': [12.34, 4.2]})
print (a.to_string (index=False))
Text Value
abcdef 12.34
x 4.20
仅打印数据帧时也是如此。
在[12]中:
print (a)
Text Value
0 abcdef 12.34
1 x 4.20
令人惊讶的是,to_string函数中的justify参数只能证明列标题的合理性。
在[13]中:
import pandas as pd
columns = ['Text', 'Value']
a = pd.DataFrame ({'Text': ['abcdef', 'x'], 'Value': [12.34, 4.2]})
print (a.to_string (justify='left', index=False))
Text Value
abcdef 12.34
x 4.20
如何控制各列的对齐设置?
答案 0 :(得分:7)
如果您愿意使用其他图书馆,tabulate会执行此操作 -
$ pip install tabulate
然后
from tabulate import tabulate
df = pd.DataFrame ({'Text': ['abcdef', 'x'], 'Value': [12.34, 4.2]})
print(tabulate(df, showindex=False, headers=df.columns))
Text Value
------ -------
abcdef 12.34
x 4.2
它还有各种其他输出格式。
答案 1 :(得分:6)
您可以使用a['Text'].str.len().max()
计算a['Text']
中最长字符串的长度,并在左对齐格式化程序N
中使用该数字'{:<Ns}'.format
:< / p>
In [211]: print(a.to_string(formatters={'Text':'{{:<{}s}}'.format(a['Text'].str.len().max()).format}, index=False))
Text Value
abcdef 12.34
x 4.20
答案 2 :(得分:2)
我将@ unutbu的方法转换为函数,因此我可以左对齐我的数据帧。
my_df = pd.DataFrame({'StringVals': ["Text string One", "Text string Two", "Text string Three"]})
def left_justified(df):
formatters = {}
for li in list(df.columns):
max = df[li].str.len().max()
form = "{{:<{}s}}".format(max)
formatters[li] = functools.partial(str.format, form)
return df.to_string(formatters=formatters, index=False)
现在这样:
print(my_df.to_string())
StringVals
0 Text string One
1 Text string Two
2 Text string Three
成为这个:
print(left_justified(my_df))
StringVals
Text string One
Text string Two
Text string Three
但请注意,数据框中的任何非字符串值都会给您带来错误:
AttributeError: Can only use .str accessor with string values, which use np.object_ dtype in pandas
如果您希望它使用非字符串值,则必须将不同的格式字符串传递给.to_string()
:
my_df2 = pd.DataFrame({'Booleans' : [False, True, True],
'Floats' : [1.0, 0.4, 1.5],
'StringVals': ["Text string One", "Text string Two", "Text string Three"]})
FLOAT_COLUMNS = ('Floats',)
BOOLEAN_COLUMNS = ('Booleans',)
def left_justified2(df):
formatters = {}
# Pass a custom pattern to format(), based on
# type of data
for li in list(df.columns):
if li in FLOAT_COLUMNS:
form = "{{!s:<5}}".format()
elif li in BOOLEAN_COLUMNS:
form = "{{!s:<8}}".format()
else:
max = df[li].str.len().max()
form = "{{:<{}s}}".format(max)
formatters[li] = functools.partial(str.format, form)
return df.to_string(formatters=formatters, index=False)
浮动和布尔值:
print(left_justified2(my_df2))
Booleans Floats StringVals
False 1.0 Text string One
True 0.4 Text string Two
True 1.5 Text string Three
注意这种方法有点像黑客。您不仅需要在单独的列表中维护列名称,还必须最好地猜测数据宽度。也许拥有更好Pandas-Fu的人可以演示如何自动解析数据帧信息以自动生成格式。
答案 3 :(得分:1)
我喜欢@unutbu 的回答(不需要任何额外的依赖)。 @JS. 的添加是朝着这个方向迈出的一步(朝着可重用的方向发展)。
由于构建格式化程序 dict 是困难的部分,让我们创建一个函数,该函数从 DataFrame 和要格式化的可选列列表创建格式化程序 dict。
def make_lalign_formatter(df, cols=None):
"""
Construct formatter dict to left-align columns.
Parameters
----------
df : pandas.core.frame.DataFrame
The DataFrame to format
cols : None or iterable of strings, optional
The columns of df to left-align. The default, cols=None, will
left-align all the columns of dtype object
Returns
-------
dict
Formatter dictionary
"""
if cols is None:
cols = df.columns[df.dtypes == 'object']
return {col: f'{{:<{df[col].str.len().max()}s}}'.format for col in cols}
让我们创建一些示例数据来演示如何使用此函数:
import pandas as pd
# Make some data
data = {'First': ['Tom', 'Dick', 'Harry'],
'Last': ['Thumb', 'Whittington', 'Potter'],
'Age': [183, 667, 23]}
# Make into a DataFrame
df = pd.DataFrame(data)
要对齐所有 DataFrame 中类型为 object 的列:
# Left align all columns
print(df.to_string(formatters=make_lalign_formatter(df),
index=False,
justify='left'))
要仅对齐'First'
列:
# Left align all columns
print(df.to_string(formatters=make_lalign_formatter(df, cols=['First']),
index=False,
justify='left'))
答案 4 :(得分:0)
这适用于Python 3.7(functools现在是该版本的一部分)
# pylint: disable=C0103,C0200,R0205
from __future__ import print_function
import pandas as pd
import functools
@staticmethod
def displayDataFrame(dataframe, displayNumRows=True, displayIndex=True, leftJustify=True):
# type: (pd.DataFrame, bool, bool, bool) -> None
"""
:param dataframe: pandas DataFrame
:param displayNumRows: If True, show the number or rows in the output.
:param displayIndex: If True, then show the indexes
:param leftJustify: If True, then use technique to format columns left justified.
:return: None
"""
if leftJustify:
formatters = {}
for columnName in list(dataframe.columns):
columnType = type(columnName) # The magic!!
# print("{} => {}".format(columnName, columnType))
if columnType == type(bool):
form = "{{!s:<8}}".format()
elif columnType == type(float):
form = "{{!s:<5}}".format()
else:
max = dataframe[columnName].str.len().max()
form = "{{:<{}s}}".format(max)
formatters[columnName] = functools.partial(str.format, form)
print(dataframe.to_string(index=displayIndex, formatters=formatters), end="\n\n")
else:
print(dataframe.to_string(index=displayIndex), end="\n\n")
if displayNumRows:
print("Num Rows: {}".format(len(dataframe)), end="\n\n")