我想使用FORTRAN格式字符串将pandas数据帧写入文件。我没有在网上找到任何东西,除了讨论这个功能如何好。有谁知道这是否可行?
我想我不需要使用fortran格式字符串...我只需要以特定格式获取输出文件,fortran可以轻松阅读。
更新:例如,我有一个具有指定fortran格式的大型数据文件。我将文件加载到我的python函数中,操纵数据,然后将操作数据导出到原始格式相同的文件中。文件格式的示例类似于:
格式(1X,F12.6,2F9.6,F11.7,T61,2F9.6,F10.7,T142,I6,1X,A2,T236,A1)
我需要以特定格式导出数据的原因是因为输出文件将被直接读入一个完善的fortran代码(意味着fortran代码不能被更改)。
答案 0 :(得分:1)
我想更大的问题是如何从熊猫输出到fortran,我不确定最好的方法,但我会尝试用to_csv()
来展示一些相当简单的解决方案。
df = pd.DataFrame({ 'x':[1.03,2.9,3.7],'y':[1,22,5] })
x y
0 1.03 1
1 2.90 22
2 3.70 5
标准的pandas输出实际上正是你在这里要求的,但我不知道除了复制和粘贴之外如何将其输入文件。也许有一种方法可以使用ipython(虽然不是我能找到的)。
这里有一些默认的csv输出,显然不是柱状的:
df.to_csv('foo.csv',index=False)
%more foo.csv
x,y
1.03,1
2.9,22
3.7,5
但是你可以用list directed input将它变成fortran。
如果您可以使用相同格式的所有数字,您可以执行以下操作:
df.astype(float).to_csv('foo.raw',index=False,float_format='%10.5f')
%more foo.raw
x,y
1.03000, 1.00000
2.90000, 22.00000
3.70000, 5.00000
这里有一些注意事项:这并不错,但仅限于强制您对所有数字使用相同的格式,例如,这对于单个数字整数来说相当浪费。此外,我尝试使用一些NaN并且这种方法效果不佳。并且那里也不需要逗号,但是当我尝试将分隔符更改为' '然后它引用了所有内容,所以我就把它留了出来。
最后,最灵活的方法可能是转换为字符串并格式化它们。这使您可以灵活地单独格式化每列。这是一个使用右对齐格式的简单示例(对于' x'宽度为8,对于' y'为4):
df.x = df.x.map('{:>8}'.format)
df.y = df.y.map('{:>4}'.format)
df.to_csv('foo.str',index=False)
%more foo.str
x,y
1.03, 1
2.9, 22
3.7, 5
我仍然无法弄清楚如何摆脱这些逗号,但这种方式确实成功处理了NaN。
答案 1 :(得分:1)
这是一个很好的整洁解决方案,它使用"angularCompilerOptions": {
"enableIvy": false
}
包(fortranformat
,https://pypi.org/project/fortranformat/)和pip install fotranformat
,让您使用标准的fortran格式字符串:
df.apply()
import fortranformat as ff
import pandas as pd
df = pd.DataFrame({
'sampleId': ['A','B','C','D'],
'var1' : [0.002,0.004,0.006,0.002],
'var2' : [1.2,1.4,1.6,1.2],
'Nobs': [32,12,9,30]
})
format_string = '(a5, f8.3, f8.1, i5)'
header_line = ff.FortranRecordWriter(format_string)
Formatted_df = df.apply(lambda x : header_line.write(x.values),axis=1)
对象将是一个Formatted_df
对象,其中数据帧的每一行都有一个字符串元素:
Series
要将其写入文件,然后可以使用>>> print(Formatted_df)
0 A 0.002 1.2 32
1 B 0.004 1.4 12
2 C 0.006 1.6 9
3 D 0.002 1.2 30
dtype: object
>>> print(Formatted_df.loc[0])
A 0.002 1.2 32
>>> print(type(Formatted_df.loc[0]))
<class 'str'>
:
to_csv
请注意,它不会包含任何列名,因此您可能希望初始化输出文件,然后追加到该文件:
Formatted_df.to_csv('formatted_df.csv',index=False,header=False)
还要注意,这是假设您已经知道数据框列的顺序。
ALSO 请注意,如果您要处理非常大的数据帧,则可能会遇到内存问题,因为output_fi='formatted_df.csv'
col_names=df.columns.tolist()
with open(output_fi,'w') as outfi:
outfi.write('# '+' '.join(col_names)+"\n")
outfi.write('# '+format_string+"\n")
Formatted_df.to_csv(output_fi,mode='a',index=False,header=False)
将是Formatted_df
的完整副本。如果是这种情况,则必须将其分块!
答案 2 :(得分:0)
我知道这不太理想,但我采取这种做法的方法是逐行打印出每条记录:
df = pd.DataFrame({'alt':[1435.2, 1234.7], 'lat':[0.145, 0.324], 'lon':[12.45, 12.23]})
with open('flight.trk', 'w') as f:
f.write("! Alt Lat Lon\n")
for ix, alt, lat, lon in df.itertuples():
f.write("{:10.2f} {:9.4f} {:9.4f}\n".format(alt, lat, lon))
请注意,我已使用itertuples
按照此处的建议(What is the most efficient way to loop through dataframes with pandas?)迭代行,但这依赖于知道列的顺序(在这种情况下按字母顺序排列)。
我已经将它用于超过10,000行的表格,虽然我没有进行任何严格的计时实验,但实际上我的经验相当快。
答案 3 :(得分:0)
稍后再讨论,这是一种适用于我的情况的解决方案(myDF
具有第一列字符串,然后具有2列浮点数)。假设您需要使用以下内容在Fortran中阅读
FORMAT (A19,F11.6,F11.6)
然后(用import numpy as np
):
np.savetxt(myfile, myDF.to_numpy(), fmt="%19s %10.6f %10.6f")
或(避免额外的空格,但不太清楚):
np.savetxt(myfile, myDF.to_numpy(), fmt="%19s%11.6f%11.6f")
(以防万一,它可以帮助别人;-))