我试图解决切片问题。我有以下数据框,df:
Feeder # 1 Feeder # 2
TimeStamp MW Month Day Hour TimeStamp MW Month Day Hour
0 2/3 1.2 1 30 22 2/3 2.4 1 30 22
1 2/4 2.3 1 31 23 2/3 4.1 1 31 23
2 2/5 3.4 2 1 0 2/3 3.7 2 1 0
共有8个馈线。
如果我想在所有Feeders中选择所有MW列,我可以这样做:
df.xs('MW', level=1, axis=1,drop_level=False)
如果我想要2号到4号馈线,我可以这样做:
df.loc[:,'Feeder #2':'Feeder #4']
但是如果我想通过以下方式在Feed 2到4中通过日期列出MW:
df.loc[:,pd.IndexSlice['Feeder #2':'Feeder #4','MW':'Day']]
我收到以下错误。
MultiIndex Slicing requires the index to be fully lexsorted tuple len (2), lexsort depth (1)
因此,如果我对数据框进行排序,那么我就能做到:
df.sortlevel(level=0,axis=1).loc[:,pd.IndexSlice['Feeder #2':'Feeder #4','Day':'MW']]
但是对数据帧进行排序会破坏标题中级别1的原始顺序 - 所有内容都按字母顺序排列(在Python中使用lexsorted?)?我想要的内容混乱:'Day':'MW'
会产生Day
,Hour
和MW
列。但我想要的是'MW':'Day'
,它会产生MW
,Month
和Day
列。
所以我的问题是:是否可以切换我的数据帧并保留列的顺序?或者,我可以lexsort数据帧,执行我需要的切片,然后将数据帧恢复原来的顺序吗?
提前致谢。
答案 0 :(得分:0)
我认为您可以使用CategoricalIndex
来保持订单:
import pandas as pd
import numpy as np
level0 = "Feeder#1 Feeder#2 Feeder#3 Feeder#4".split()
level1 = "TimeStamp MW Month Day Hour".split()
idx0 = pd.CategoricalIndex(level0, level0, ordered=True)
idx1 = pd.CategoricalIndex(level1, level1, ordered=True)
columns = pd.MultiIndex.from_product([idx0, idx1])
df = pd.DataFrame(np.random.randint(0, 10, (10, 20)), columns=columns)
然后你可以这样做:
df.loc[:, pd.IndexSlice["Feeder#2":"Feeder#3", "MW":"Day"]]
修改强>
将级别转换为CategoricalIndex
:
columns = df.columns
for i in range(columns.nlevels):
level = pd.unique(columns.get_level_values(i))
cidx = pd.CategoricalIndex(level, level, sorted=True)
print(cidx)