我想我应该分享一下,因为我在SO上搜索了一下,却没有找到我需要的东西。
我想甩一个 pd.DataFrame
到一个yaml文件中。
Timestamps
应该很好地显示出来,而不是像默认的那样。
date: !!python/object/apply:pandas._libs.tslibs.timestamps.Timestamp
- 1589241600000000000
- null
- null
另外,输出应该是正确的YaML格式,也就是说,它应该是可读的。yaml.load
. 输出的数据应该相当简洁,即喜欢 "flow "格式。
作为一个例子,这里有一些数据。
df = pd.DataFrame([
dict(
date=pd.Timestamp.now().normalize() - pd.Timedelta('1 day'),
x=0,
b='foo',
c=[1,2,3,4],
other_t=pd.Timestamp.now(),
),
dict(
date=pd.Timestamp.now().normalize(),
x=1,
b='bar',
c=list(range(32)),
other_t=pd.Timestamp.now(),
),
]).set_index('date')
这是我想出的办法。它有一些自定义的 Dumper
办理 Timestamp
. 输出的结果更加清晰,而且还是有效的 yaml。加载后,yaml会识别有效的日期时间格式(我想是ISO格式),并将这些格式重新创建为 datetime
. 事实上,我们可以把它读回一个 DataFrame
其中,这些 datetime
自动转换为 Timestamp
. 在对指数进行小幅重设后,我们观察到,新的 df
与原来的相同。
import yaml
from yaml import CDumper
from yaml.representer import SafeRepresenter
import datetime
class TSDumper(CDumper):
pass
def timestamp_representer(dumper, data):
return SafeRepresenter.represent_datetime(dumper, data.to_pydatetime())
TSDumper.add_representer(datetime.datetime, SafeRepresenter.represent_datetime)
TSDumper.add_representer(pd.Timestamp, timestamp_representer)
有了这个,现在我们可以做。
text = yaml.dump(
df.reset_index().to_dict(orient='records'),
sort_keys=False, width=72, indent=4,
default_flow_style=None, Dumper=TSDumper,
)
print(text)
输出比较干净。
- date: 2020-05-12 00:00:00
x: 0
b: foo
c: [1, 2, 3, 4]
other_t: 2020-05-13 02:30:23.422589
- date: 2020-05-13 00:00:00
x: 1
b: bar
c: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
other_t: 2020-05-13 02:30:23.422613
现在,我们可以把它装回去
df2 = pd.DataFrame(yaml.load(text, Loader=yaml.SafeLoader)).set_index('date')
现在,我们可以把这个装回去:
df2.equals(df)
# True