Python Pandas,将DataFrame写入固定宽度文件(to_fwf?)

时间:2013-05-10 20:23:32

标签: python pandas fixed-width

我看到Pandas有read_fwf,但它有DataFrame.to_fwf之类的东西吗?我正在寻找对字段宽度,数值精度和字符串对齐的支持。似乎DataFrame.to_csv没有这样做。 numpy.savetxt确实如此,但我不想这样做:

numpy.savetxt('myfile.txt', mydataframe.to_records(), fmt='some format')

这似乎不对。非常感谢您的想法。

7 个答案:

答案 0 :(得分:6)

在pandas中有人implements之前,你可以使用tabulate包:

import pandas as pd
from tabulate import tabulate

def to_fwf(df, fname):
    content = tabulate(df.values.tolist(), list(df.columns), tablefmt="plain")
    open(fname, "w").write(content)

pd.DataFrame.to_fwf = to_fwf

答案 1 :(得分:5)

one for Sheets if the form submits to a spreadsheet

上面的问题答案帮助了我。这不是最好的,但在np.savetxt(r'c:\data\np.txt', df.values, fmt='%d') 存在之前,这对我来说就是诀窍......

np.savetxt(r'c:\data\np.txt', df.values, fmt='%10.5f')

ambari-server

答案 2 :(得分:3)

对于每列的自定义格式,您可以设置整行的格式。 fmt param为每一行提供格式

with open('output.dat') as ofile:
     fmt = '%.0f %02.0f %4.1f %3.0f %4.0f %4.1f %4.0f %4.1f %4.0f'
     np.savetxt(ofile, df.values, fmt=fmt)

答案 3 :(得分:2)

我相信你找到了解决这个问题的办法,但是对于其他任何好奇的人...... 如果将DF写入列表,则可以通过给出'format as a string'来将其写入文件.format(list indices) 例如:

df=df.fillna('')
outF = 'output.txt'      
dbOut = open(temp, 'w')
v = df.values.T.tolist()        
for i in range(0,dfRows):       
    dbOut.write(( \
    '{:7.2f}{:>6.2f}{:>2.0f}{:>4.0f}{:>5.0f}{:6.2f}{:6.2f}{:6.2f}{:6.1f {:>15}{:>60}'\
    .format(v[0][i],v[1][i],v[2][i],v[3][i],v[4][i],v[5][i],v[6][i],v[7][i],v[8][i],\
    v[9][i],v[10][i]) ))
    dbOut.write("\n")
dbOut.close

请确保使用正确的格式匹配每个索引:)

希望有所帮助!

答案 4 :(得分:1)

找到了一个非常简单的解决方案! (蟒蛇)。在捕捉的代码中,我试图将DataFrame写入位置文件。 “ finalDataFrame.values.tolist()”将返回ua列表,其中DataFrame的每一行都变成另一个列表,只是[['Camry',2019,'Toyota'],['Mustang','2016', '福特']]。之后,借助for循环和if语句,我尝试设置其修复长度。休息很明显!

 with open (FilePath,'w') as f:
    for i in finalDataFrame.values.tolist():
        widths=(0,0,0,0,0,0,0)
        if i[2] == 'nan':
            i[2]=''
            for h in range(7):
                i[2]= i[2] + ' '
        else:
            x=7-len(str(i[2]))
            a=''
            for k in range(x):
               a=a+' '
            i[2]=str(i[2])+a

        if i[3] == '':
            i[3]=''
            for h in range(25):
                i[3]=i[3]+' '
        else:
            x = 25 - len(i[3])
            print(x)
            a = ''
            for k in range(x):
                a = a + ' '
            print(a)
            i[3] = i[3] + a


        i[4] = str(i[4])[:10]

        q="".join("%*s" % i for i in zip(widths, i))
        f.write(q+'\n')

答案 5 :(得分:0)

pandas.DataFrame.to_string()是您所需要的。唯一的技巧是如何管理索引。

忽略索引

如果您不在乎索引:

# write
df.to_string(filepath, index=False)

# read
df = pd.read_fwf(filepath)

句柄索引

如果要检索pandas.Indexpandas.MultiIndex

# write
df.reset_index().to_string(filepath, index=False)

# read
df = pd.read_fwf(filepath).set_index(index_names)

如果您的Index在写时没有名字,reset_index()应该将其分配给列"index"

如果您的MultiIndex没有名称,则应将其分配给列["level_0", "level_1", ...]

答案 6 :(得分:0)

根据别人的回答,这是我写的摘录,而不是最佳的编码和性能:

import pandas as pd
import pickle
import numpy as np
from tabulate import tabulate


left_align_gen = lambda length, value: eval(r"'{:<<<length>>}'.format('''<<value>>'''[0:<<length>>])".replace('<<length>>', str(length)).replace('<<value>>', str(value)))
right_align_gen = lambda length, value: eval(r"'{:><<length>>}'.format('''<<value>>'''[0:<<length>>])".replace('<<length>>', str(length)).replace('<<value>>', str(value)))

# df = pd.read_pickle("dummy.pkl")
with open("df.pkl", 'rb') as f:
    df = pickle.load(f)

# field width defines here, width of each field
widths=(22, 255, 14, 255, 14, 255, 255, 255, 255, 255, 255, 22, 255, 22, 255, 255, 255, 22, 14, 14, 255, 255, 255, 2, )

# format datetime
df['CREATED_DATE'] = df['CREATED_DATE'].apply(lambda x: x.to_pydatetime().strftime('%Y%m%d%H%M%S'))
df['LAST_MODIFIED_DATE'] = df['LAST_MODIFIED_DATE'].apply(lambda x: x.to_pydatetime().strftime('%Y%m%d%H%M%S'))
df['TERMS_ACCEPTED_DATE'] = df['TERMS_ACCEPTED_DATE'].apply(lambda x: x.to_pydatetime().strftime('%Y%m%d%H%M%S'))
df['PRIVACY_ACCEPTED_DATE'] = df['PRIVACY_ACCEPTED_DATE'].apply(lambda x: x.to_pydatetime().strftime('%Y%m%d%H%M%S'))


# print(type(df.iloc[0]['CREATED_DATE']))
# print(df.iloc[0])
record_line_list = []
# for row in df.iloc[:10].itertuples():
for row in [tuple(x) for x in df.to_records(index=False)]:
    record_line_list.append("".join(left_align_gen(length, value) for length, value in zip(widths, row)))

with open('output.txt', 'w') as f:
    f.write('\n'.join(record_line_list))

Github gist