簡體   English   中英

僅重新索引 MultiIndex 數據幀的級別,reindex() 損壞了嗎?

[英]Reindexing only level of a MultiIndex dataframe, reindex() broken?

我嘗試僅在一個級別上使用兩個或多個索引重新索引數據幀,但是使用.reindex()level參數,正如我在這個答案中看到的那樣,似乎除了預期的行為之外什么都不做。

這是我嘗試使用的代碼:

import pandas as pd

dtest = pd.DataFrame([['Martin', 'room_1', 3],
                      ['Martin', 'room_2', 2],
                      ['Georges', 'room_2', 4],
                      ['Georges', 'room_1', 12]],
                     columns=['name', 'room', 'time_spent'])
dtest.set_index(['name', 'room',], inplace=True)
display(dtest)
print(dtest.reindex(
    ['room_1', 'room_2', 'room_3'], level=1, fill_value=0))

哪個輸出

                time_spent
name    room              
Martin  room_1           3
        room_2           2
Georges room_1          12
        room_2           4

而我期待的輸出是

                time_spent
name    room              
Martin  room_1           3
        room_2           2
        room_3           0
Georges room_1          12
        room_2           4
        room_3           0

reindex()實際上什么也沒做。

我是否錯過了使用reindex的重要細節,或者有什么問題?

我正在使用 Python 3.6.7(v3.6.7:6ec5cf24b7,2018 年 10 月 20 日,03:02:14)的最新版本的 Pandas。

接受答案后編輯

我接受了@anky_91 的回答,他實際上提供了兩種不同的解決方案。 由於我的實際用例涉及多索引中的更多級別,讓我用更多級別強調他的兩個解決方案的行為。

起始數據幀現在由

import pandas as pd

dtest2 = pd.DataFrame([['2020-01-05', 'Martin', 'room_1', 3],
                      ['2020-01-05', 'Martin', 'room_2', 2],
                      ['2020-01-06', 'Georges', 'room_2', 4],
                      ['2020-01-06', 'Georges', 'room_1', 12]],
                     columns=['date', 'name', 'room', 'time_spent'])
dtest2.set_index(['date', 'name', 'room',], inplace=True)
print(dtest2)

哪個輸出

                           time_spent
date       name    room              
2020-01-05 Martin  room_1           3
                   room_2           2
2020-01-06 Georges room_2           4
                   room_1          12

適應這種情況的第一個解決方案是

mux = pd.MultiIndex.from_product((dtest2.index.get_level_values(0).unique(),
                                  dtest2.index.get_level_values(1).unique(),
                                  ['room_1', 'room_2', 'room_3']
                            ))
final_first_solution = dtest2.reindex(mux,fill_value=0)
print(final_first_solution)

哪個輸出

                           time_spent
2020-01-05 Martin  room_1           3
                   room_2           2
                   room_3           0
           Georges room_1           0
                   room_2           0
                   room_3           0
2020-01-06 Martin  room_1           0
                   room_2           0
                   room_3           0
           Georges room_1          12
                   room_2           4
                   room_3           0

這不是我想要的輸出,因為 Martin 只需要出現在 2020-01-05,而 Georges 只需要出現在 2020-01-06。 換句話說,我只想擴展最后一層room上的索引。 但是,我設法調整了第二個解決方案以獲得我想要的輸出:

final_second_solution = dtest2.unstack((0, 1)).reindex(['room_1', 'room_2', 'room_3'], fill_value=0)\
        .stack((-2, -1)).swaplevel(i=-1, j=0).swaplevel(i=1, j=0).sort_index()
print(final_second_solution)

正確地給我

                           time_spent
date       name    room              
2020-01-05 Martin  room_1         3.0
                   room_2         2.0
                   room_3         0.0
2020-01-06 Georges room_1        12.0
                   room_2         4.0
                   room_3         0.0

這就是為什么我接受了答案。 謝謝!

針對不同的用例編輯 2

經過更多測試,當您沒有添加新房間,而是想要完成數據框中出現的所有房間時,上述解決方案失敗。 但是解決方案更簡單,因為在這種情況下unstack已經創建了缺失的行,所以我們只需要使用fillna而不是reindex 以下代碼

import pandas as pd

dtest3 = pd.DataFrame([['2020-01-05', 'Martin', 'room_1', 3],
                      ['2020-01-06', 'Georges', 'room_2', 4]],
                     columns=['date', 'name', 'room', 'time_spent'])
dtest3.set_index(['date', 'name', 'room',], inplace=True)
print(dtest3)
final_third_solution = dtest3.unstack((0, 1)).fillna(0).stack((-2, -1)).reorder_levels([1,2,0]).sort_index()
print(final_third_solution)

因此給出了想要的結果

                           time_spent
date       name    room              
2020-01-05 Martin  room_1         3.0
                   room_2         0.0
2020-01-06 Georges room_1         0.0
                   room_2         4.0

(我還在評論中包含了使用reorder_levels而不是使用多個swaplevel )。

使用.fillna(0).reindex(..., fill_value=0)應該包含您想要完成和添加新元素的兩種情況。

您需要為此使用pd.MultiIndex.from_product()get_level_values創建一個多索引:

mux=(pd.MultiIndex.from_product((dtest.index.get_level_values(0).unique()
                             ,['room_1', 'room_2', 'room_3'])))
final=dtest.reindex(mux,fill_value=0)

                time_spent
Martin  room_1           3
        room_2           2
        room_3           0
Georges room_1          12
        room_2           4
        room_3           0

如果您只想使用現有索引添加另一個索引,請使用Index.unionfrom_product()參數:

mux=(pd.MultiIndex.from_product((dtest.index.get_level_values(0).unique()
        ,dtest.index.get_level_values(1).unique().union(['room3'],sort=False))))
final=dtest.reindex(mux,fill_value=0)

                time_spent
Martin  room_1           3
        room_2           2
        room_3           0
Georges room_1          12
        room_2           4
        room_3           0

添加另一個梅托德stack()unstack()swaplevel

final=dtest.unstack(0).reindex(['room_1', 'room_2', 'room_3']
                     ,fill_value=0).stack().swaplevel().sort_index()

                time_spent
name    room              
Georges room_1          12
        room_2           4
        room_3           0
Martin  room_1           3
        room_2           2
        room_3           0

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM