英文:
Dropped columns reappear in columns.level
问题
我有一个带有多级索引的DataFrame。
当我删除一列(例如,包含NaN的列)时,当我调用df.columns.levels[1]
时,仍然会出现这个列名。
最小工作示例:
# 创建DataFrame
midx = pd.MultiIndex.from_tuples([('A', 'aa'), ('A', 'bb'), ('B', 'cc'), ('B', 'dd')])
mydf = pd.DataFrame(np.random.randn(5, 4), columns=midx)
mydf.loc[1, ('B', 'cc')] = np.nan
print(mydf)
>> A B
aa bb cc dd
0 -0.565250 -1.267290 -1.811422 -0.242648
1 0.138827 0.182022 NaN -0.286807
2 0.037163 -1.867622 1.259539 -0.485333
3 1.283082 1.030154 0.678748 -0.200731
4 -0.405116 -0.963670 -0.405438 -1.695403
# 删除带有NaN的列
mydf.dropna(how='any', axis=1, inplace=True)
print(mydf)
>> A B
aa bb dd
0 -0.565250 -1.267290 -0.242648
1 0.138827 0.182022 -0.286807
2 0.037163 -1.867622 -0.485333
3 1.283082 1.030154 -0.200731
4 -0.405116 -0.963670 -1.695403
mydf.columns.levels[1]
>> Index(['aa', 'bb', 'cc', 'dd'], dtype='object')
我尝试过的替代方法,最终结果都相同:
new_df = mydf.dropna(how='any', axis=1)
new_df = mydf.dropna(how='any', axis=1).copy()
我需要访问第1级中存在的列名列表。
我找到了一个可行的解决方法,但我需要了解为什么上面的代码不按预期工作。
英文:
I have a DataFrame with MultiIndex.
When I drop a column (e.g., containing a NaN) this column name still appears, when I call df.columns.levels[1]
.
Minimal working example:
# Create DataFrame
midx = pd.MultiIndex.from_tuples([('A','aa'),('A','bb'),('B','cc'),('B','dd')])
mydf = pd.DataFrame(np.random.randn(5,4), columns=midx)
mydf.loc[1,('B','cc')] = np.nan
print(mydf)
>> A B
aa bb cc dd
0 -0.565250 -1.267290 -1.811422 -0.242648
1 0.138827 0.182022 NaN -0.286807
2 0.037163 -1.867622 1.259539 -0.485333
3 1.283082 1.030154 0.678748 -0.200731
4 -0.405116 -0.963670 -0.405438 -1.695403
# Drop column with NaN
mydf.dropna(how='any', axis=1, inplace=True)
print(mydf)
>> A B
aa bb dd
0 -0.565250 -1.267290 -0.242648
1 0.138827 0.182022 -0.286807
2 0.037163 -1.867622 -0.485333
3 1.283082 1.030154 -0.200731
4 -0.405116 -0.963670 -1.695403
mydf.columns.levels[1]
>> Index(['aa', 'bb', 'cc', 'dd'], dtype='object')
Alternatives I've tried, all ending with the same results:
new_df = mydf.dropna(how='any', axis=1)
new_df = mydf.dropna(how='any', axis=1).copy()
I need to access the list of present column names on level 1.
I have found a doable work-around, but I need to understand why this code above is not working as intended.
答案1
得分: 2
不要被MultiIndex
(由单个索引组合而成)和每个Index
级别所混淆。MultiIndex
代表了组成它的各个单独索引的可见子集(最好是笛卡尔积)。
# Index,级别 0
>>> mydf.columns.levels[0]
# Index,级别 1
>>> mydf.columns.levels[1]
Index(['aa', 'bb', 'cc', 'dd'], dtype='object')
# Values,级别 0
>>> mydf.columns.get_level_values(0)
Index(['A', 'A', 'B'], dtype='object')
# Values,级别 1
>>> mydf.columns.get_level_values(1)
Index(['aa', 'bb', 'dd'], dtype='object')
# 笛卡尔积 / 密集多级索引
>>> pd.MultiIndex.from_product([mydf.columns.levels[0], mydf.columns.levels[1]])
MultiIndex([('A', 'aa'),
('A', 'bb'),
('A', 'cc'),
('A', 'dd'),
('B', 'aa'),
('B', 'bb'),
('B', 'cc'),
('B', 'dd')],
)
因此,如果您有一个不再被引用的元素,就像@ScottBoston所说,您可以使用remove_unused_levels
。
要仅使用已使用的级别重构MultiIndex,可以使用
remove_unused_levels()
方法。
>>> mydf.columns.remove_unused_levels().levels
FrozenList([['A', 'B'], ['aa', 'bb', 'dd']])
# level 0 --^ level 1 --^
更多关于MultiIndex中定义级别/高级索引的信息。
英文:
Don't be confused by the MultiIndex
(a combination of single indexes) and each Index
level. The MultiIndex
represents a visible subset (at best the cartesian product) of the individual indexes that compose it.
# Index, level 0
>>> mydf.columns.levels[0]
# Index, level 1
>>> mydf.columns.levels[1]
Index(['aa', 'bb', 'cc', 'dd'], dtype='object')
# Values, level 0
>>> mydf.columns.get_level_values(0)
Index(['A', 'A', 'B'], dtype='object')
# Values, level 1
>>> mydf.columns.get_level_values(1)
Index(['aa', 'bb', 'dd'], dtype='object')
# Cartesian product / dense multi-index
>>> pd.MultiIndex.from_product([mydf.columns.levels[0], mydf.columns.levels[1]])
MultiIndex([('A', 'aa'),
('A', 'bb'),
('A', 'cc'),
('A', 'dd'),
('B', 'aa'),
('B', 'bb'),
('B', 'cc'),
('B', 'dd')],
)
So if you have an element that is no longer referenced, as @ScottBoston said, you can use remove_unused_levels
.
> To reconstruct the MultiIndex with only the used levels, the remove_unused_levels() method may be used.
>>> mydf.columns.remove_unused_levels().levels
FrozenList([['A', 'B'], ['aa', 'bb', 'dd']])
# level 0 --^ level 1 --^
答案2
得分: 1
使用 pd.MultiIndex.remove_unused_levels
:
mydf.columns.levels[1]
#Index(['aa', 'bb', 'cc', 'dd'], dtype='object')
mydf.columns = mydf.columns.remove_unused_levels()
mydf.columns.levels[1]
#Index(['aa', 'bb', 'dd'], dtype='object')
英文:
Use pd.MultiIndex.remove_unused_levels
:
mydf.columns.levels[1]
#Index(['aa', 'bb', 'cc', 'dd'], dtype='object')
mydf.columns = mydf.columns.remove_unused_levels()
mydf.columns.levels[1]
#Index(['aa', 'bb', 'dd'], dtype='object')
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论