问题描述
我有一个pd.DataFrame
,其中包含两级列。我需要保留n
的最后level 1
列并删除所有以前的列。 level 0
的所有列中的列数不一定相等。
df = pd.DataFrame(np.random.randint(low=1,high=5,size=(4,12)))
df.columns = pd.MultiIndex.from_product([[1,2,3],['A','B','C','D']])
df.drop((2,'A'),axis = 1,inplace = True)
df.drop((3,'C'),inplace = True)
1 2 3
A B C D B C D B D
0 3 1 4 3 4 2 4 4 4
1 4 1 4 1 1 2 4 1 1
2 3 4 3 2 3 4 3 3 1
3 2 4 4 1 4 1 1 2 3
预期结果:
1 2 3
C D C D B D
0 4 3 2 4 4 4
1 4 1 2 4 1 1
2 3 2 4 3 3 1
3 4 1 1 1 2 3
解决方法
将ascending=False
的{{3}}与MultiIndex
的反面计数器一起使用,并过滤GroupBy.cumcount
中的最后2列,同样cumcount
失败,且水平为列,因此添加了DataFrame.loc
:
df = df.loc[:,df.columns.to_frame().groupby(level=0).cumcount(ascending=False) < 2]
print (df)
1 2 3
C D C D B D
0 4 4 2 1 3 3
1 1 1 2 1 4 2
2 1 1 2 3 4 2
3 4 3 1 3 4 4
详细信息:
print (df.columns.to_frame().groupby(level=0).cumcount(ascending=False))
1 A 3
B 2
C 1
D 0
2 B 2
C 1
D 0
3 B 1
D 0
dtype: int64
print (df.columns.to_frame().groupby(level=0).cumcount(ascending=False) < 2)
1 A False
B False
C True
D True
2 B False
C True
D True
3 B True
D True
dtype: bool
另一个方法是过滤最后一列,然后按MultiIndex.to_frame
进行过滤:
df = df.loc[:,df.columns.isin(df.columns.to_frame().groupby(level=0).tail(2).index)]
print (df)
1 2 3
C D C D B D
0 3 1 3 2 1 1
1 3 2 4 2 3 1
2 2 4 3 3 1 3
3 1 3 4 1 3 3
,
遍历各列以仅保留所需的列:
from collections import defaultdict
from itertools import chain
d = defaultdict(list)
for k,v in df.columns:
d[k].append((k,v))
#assumption is you need the last two columns,so negative indexing :
columns = list(chain.from_iterable(value[-2:] for key,value in d.items()))
df.loc[:,columns]
1 2 3
C D C D B D
0 4 3 2 4 4 4
1 4 1 2 4 1 1
2 3 2 4 3 3 1
3 4 1 1 1 2 3