【问题标题】:Python Pandas, write DataFrame to fixed-width file (to_fwf?)Python Pandas,将 DataFrame 写入固定宽度文件(to_fwf?)
【发布时间】:2013-05-10 20:23:32
【问题描述】:

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

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

这似乎是错误的。非常感谢您的想法。

【问题讨论】:

  • 看看to_string方法,看看你能不能做你想做的事。
  • 这看起来很接近。如果任何两个浮点或字符串列具有不同的格式,我似乎必须为每列提供一个格式化函数。它可以解决问题,只是看起来有点笨拙。我希望我错过了什么。谢谢!
  • pandas df.to_csv 有一个 sep =" " 参数,在这种情况下将逗号更改为空格或空字符串。结合方法的格式化程序应该可以做到。
  • @Joop 实际上使用空字符串作为分隔符的df.to_csv() 方法会给出错误TypeError: delimiter must be set
  • true.. 将空字符串传递给方法会造成混乱,请忽略我对空字符串的引用。也许尝试 pandas “to_string” 方法会有所帮助。 if 有相当不错的 formatters 参数

标签: python pandas fixed-width


【解决方案1】:

直到有人在熊猫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

【讨论】:

  • 这对我来说效果很好。手动弄乱字符串空间格式的方法要清醒得多。
【解决方案2】:

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

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】:

    Python, Pandas : write content of DataFrame into text File

    上面的问题对我有帮助。这不是最好的,但在to_fwf 存在之前,这对我有用...

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

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

    【讨论】:

    • IMO 这比 tabulate 好,因为 numpy 包含在 pandas 中,因此不需要额外的库
    【解决方案4】:

    pandas.DataFrame.to_string() 就是你所需要的。唯一的窍门是如何管理索引。

    # Write
    # df.reset_index(inplace=True)  # uncomment if the index matters
    df.to_string(filepath, index=False)
    
    # Read
    df = pd.read_fwf(filepath)
    # df.set_index(index_names, inplace=True)  # uncomment if the index matters
    

    如果索引是没有名称的pandas.Indexreset_index() 应将其分配给列"index"。如果是没有名称的pandas.MultiIndex,则应将其分配给列["level_0", "level_1", ...]

    【讨论】:

      【解决方案5】:

      我相信您已经找到了解决此问题的方法,但对于其他好奇的人... 如果将 DF 写入列表,则可以通过给出“格式为字符串”将其写入文件。格式(列表索引) 例如:

      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
      

      只需确保将每个索引与正确的格式匹配即可:)

      希望有帮助!

      【讨论】:

        【解决方案6】:

        找到了一个非常简单的解决方案! (Python)。在捕捉的代码中,我试图将 DataFrame 写入位置文件。 "finalDataFrame.values.tolist()" 将返回一个列表,其中 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')
        

        【讨论】:

          【解决方案7】:

          根据别人的回答,这里是我写的sn-p,在编码和性能上不是最好的:

          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

          【讨论】:

            猜你喜欢
            • 2021-02-25
            • 1970-01-01
            • 1970-01-01
            • 2013-05-31
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多