MultiIndex
有可能成为“面板”数据的有用且更灵活的替代方法。更加灵活,因为尽管传统面板在面板之间具有相同的列,但是通过分层索引,您可以根据需要对列进行分组。但是,当并非每一列都与日期关联时,我找不到一种简便的方法来保护MultiIndex中的日期dtype
。
例如,以DataFrame
开头,其中日期作为每一列的层次结构标签的一部分:
import pandas as pd
letters = ["a", "b"]
dates = list(pd.date_range(start="2019-11-12", freq="D", periods=2))
index = pd.MultiIndex.from_product([letters, dates], names=[None, "Date"])
df = pd.DataFrame(columns=index)
df.loc[0, :] = 1
df.columns.get_level_values("Date").dtype
dtype('<M8[ns]')
在严重扭曲的情况下,您可以添加没有“日期”标签的列。
df2 = pd.concat((
df,
pd.DataFrame(
data=["A"],
columns=pd.MultiIndex.from_product([["good"], [pd.np.nan]]),
)),
axis=1
)
df2.columns.get_level_values("Date").dtype
dtype('<M8[ns]')
不仅保留了“日期”上的dtype
,而且检查df2.columns
节目的“日期”级别也没有延长。
必须有一种更简单的方法,例如分配给新标签:
df3 = df.copy()
df3["bad"] = "A"
df3.columns.get_level_values("Date").dtype
dtype('O')
“日期”级别失去了日期类型,而获得了一个等于空字符串的新值。空字符串!也不使用.loc
。有建议吗?
回复评论:
df2.columns
MultiIndex(levels=[['a', 'b', 'good'], [2019-11-12 00:00:00, 2019-11-13 00:00:00]],
codes=[[0, 0, 1, 1, 2], [0, 1, 0, 1, -1]],
names=[None, 'Date'])
“日期”有两个级别。
df3.columns
MultiIndex(levels=[['a', 'b', 'bad'], [2019-11-12 00:00:00, 2019-11-13 00:00:00, '']],
codes=[[0, 0, 1, 1, 2], [0, 1, 0, 1, 2]],
names=[None, 'Date'])
从df3 = df.copy()
开始,分配给df3["bad"]
将添加到“日期”级别。它成为原始的两个,并带有空字符串。或使用df3[("bad", None)] = "A"
的附加值是NaT
。