删除的列重新出现在列级别中

huangapple go评论115阅读模式
英文:

Dropped columns reappear in columns.level

问题

我有一个带有多级索引的DataFrame。

当我删除一列(例如,包含NaN的列)时,当我调用df.columns.levels[1]时,仍然会出现这个列名。

最小工作示例:

  1. # 创建DataFrame
  2. midx = pd.MultiIndex.from_tuples([('A', 'aa'), ('A', 'bb'), ('B', 'cc'), ('B', 'dd')])
  3. mydf = pd.DataFrame(np.random.randn(5, 4), columns=midx)
  4. mydf.loc[1, ('B', 'cc')] = np.nan
  5. print(mydf)
  6. >> A B
  7. aa bb cc dd
  8. 0 -0.565250 -1.267290 -1.811422 -0.242648
  9. 1 0.138827 0.182022 NaN -0.286807
  10. 2 0.037163 -1.867622 1.259539 -0.485333
  11. 3 1.283082 1.030154 0.678748 -0.200731
  12. 4 -0.405116 -0.963670 -0.405438 -1.695403
  13. # 删除带有NaN的列
  14. mydf.dropna(how='any', axis=1, inplace=True)
  15. print(mydf)
  16. >> A B
  17. aa bb dd
  18. 0 -0.565250 -1.267290 -0.242648
  19. 1 0.138827 0.182022 -0.286807
  20. 2 0.037163 -1.867622 -0.485333
  21. 3 1.283082 1.030154 -0.200731
  22. 4 -0.405116 -0.963670 -1.695403
  23. mydf.columns.levels[1]
  24. >> Index(['aa', 'bb', 'cc', 'dd'], dtype='object')

我尝试过的替代方法,最终结果都相同:

  1. new_df = mydf.dropna(how='any', axis=1)
  2. 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:

  1. # Create DataFrame
  2. midx = pd.MultiIndex.from_tuples([('A','aa'),('A','bb'),('B','cc'),('B','dd')])
  3. mydf = pd.DataFrame(np.random.randn(5,4), columns=midx)
  4. mydf.loc[1,('B','cc')] = np.nan
  5. print(mydf)
  6. >> A B
  7. aa bb cc dd
  8. 0 -0.565250 -1.267290 -1.811422 -0.242648
  9. 1 0.138827 0.182022 NaN -0.286807
  10. 2 0.037163 -1.867622 1.259539 -0.485333
  11. 3 1.283082 1.030154 0.678748 -0.200731
  12. 4 -0.405116 -0.963670 -0.405438 -1.695403
  13. # Drop column with NaN
  14. mydf.dropna(how='any', axis=1, inplace=True)
  15. print(mydf)
  16. >> A B
  17. aa bb dd
  18. 0 -0.565250 -1.267290 -0.242648
  19. 1 0.138827 0.182022 -0.286807
  20. 2 0.037163 -1.867622 -0.485333
  21. 3 1.283082 1.030154 -0.200731
  22. 4 -0.405116 -0.963670 -1.695403
  23. mydf.columns.levels[1]
  24. >> Index(['aa', 'bb', 'cc', 'dd'], dtype='object')

Alternatives I've tried, all ending with the same results:

  1. new_df = mydf.dropna(how='any', axis=1)
  2. 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代表了组成它的各个单独索引的可见子集(最好是笛卡尔积)。

  1. # Index,级别 0
  2. >>> mydf.columns.levels[0]
  3. # Index,级别 1
  4. >>> mydf.columns.levels[1]
  5. Index(['aa', 'bb', 'cc', 'dd'], dtype='object')
  6. # Values,级别 0
  7. >>> mydf.columns.get_level_values(0)
  8. Index(['A', 'A', 'B'], dtype='object')
  9. # Values,级别 1
  10. >>> mydf.columns.get_level_values(1)
  11. Index(['aa', 'bb', 'dd'], dtype='object')
  12. # 笛卡尔积 / 密集多级索引
  13. >>> pd.MultiIndex.from_product([mydf.columns.levels[0], mydf.columns.levels[1]])
  14. MultiIndex([('A', 'aa'),
  15. ('A', 'bb'),
  16. ('A', 'cc'),
  17. ('A', 'dd'),
  18. ('B', 'aa'),
  19. ('B', 'bb'),
  20. ('B', 'cc'),
  21. ('B', 'dd')],
  22. )

因此,如果您有一个不再被引用的元素,就像@ScottBoston所说,您可以使用remove_unused_levels

要仅使用已使用的级别重构MultiIndex,可以使用remove_unused_levels()方法。

  1. >>> mydf.columns.remove_unused_levels().levels
  2. FrozenList([['A', 'B'], ['aa', 'bb', 'dd']])
  3. # 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.

  1. # Index, level 0
  2. >>> mydf.columns.levels[0]
  3. # Index, level 1
  4. >>> mydf.columns.levels[1]
  5. Index(['aa', 'bb', 'cc', 'dd'], dtype='object')
  6. # Values, level 0
  7. >>> mydf.columns.get_level_values(0)
  8. Index(['A', 'A', 'B'], dtype='object')
  9. # Values, level 1
  10. >>> mydf.columns.get_level_values(1)
  11. Index(['aa', 'bb', 'dd'], dtype='object')
  12. # Cartesian product / dense multi-index
  13. >>> pd.MultiIndex.from_product([mydf.columns.levels[0], mydf.columns.levels[1]])
  14. MultiIndex([('A', 'aa'),
  15. ('A', 'bb'),
  16. ('A', 'cc'),
  17. ('A', 'dd'),
  18. ('B', 'aa'),
  19. ('B', 'bb'),
  20. ('B', 'cc'),
  21. ('B', 'dd')],
  22. )

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.

  1. >>> mydf.columns.remove_unused_levels().levels
  2. FrozenList([['A', 'B'], ['aa', 'bb', 'dd']])
  3. # level 0 --^ level 1 --^

More on Defined levels in MultiIndex / advanced indexing

答案2

得分: 1

使用 pd.MultiIndex.remove_unused_levels

  1. mydf.columns.levels[1]
  2. #Index(['aa', 'bb', 'cc', 'dd'], dtype='object')
  3. mydf.columns = mydf.columns.remove_unused_levels()
  4. mydf.columns.levels[1]
  5. #Index(['aa', 'bb', 'dd'], dtype='object')
英文:

Use pd.MultiIndex.remove_unused_levels:

  1. mydf.columns.levels[1]
  2. #Index(['aa', 'bb', 'cc', 'dd'], dtype='object')
  3. mydf.columns = mydf.columns.remove_unused_levels()
  4. mydf.columns.levels[1]
  5. #Index(['aa', 'bb', 'dd'], dtype='object')

huangapple
  • 本文由 发表于 2023年6月19日 20:47:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/76506784.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定