簡體   English   中英

Pandas:基於非多索引掩碼覆蓋多索引 dataframe 中的值

[英]Pandas: overwrite values in a multiindex dataframe based on a non-multiindex mask

這是我第一次在這里發布自己的問題。 到目前為止,我幾乎總是在現有問題中找到解決我的問題的方法(多好的論壇和社區。),不過請多多包涵。 如果這個問題(或一個非常相似的問題)已經在 stackoverflow 的其他地方被問到和回答過。

我有一個多索引 dataframe ( test_data ),它包含同一組城市(內部級別)和相同年份范圍(列)的不同變量(外部級別),如下所示:

             1990  1991  1992  1993  1994
VAR CITY
1   Berlin    40    41    42    43    44
    Paris     36    35    34    33    32
    London    30    30    30    30    30
2   Berlin    35    34    33    32    31
    Paris     39    38    39    40    41
    London    45    44    43    42    41
3   Berlin    24    25    26    27    28
    Paris     24    24    25    26    27
    London    29    29    29    30    31
2m  Berlin     1     2     3     4     5
    Paris      2     3     4     5     6
    London     3     4     5     6     7

哪一個可以從這段代碼中獲得:

test_dict = {(1,'Berlin'): [40,41,42,43,44],
             (1,'Paris'):  [36,35,34,33,32],
             (1,'London'): [30,30,30,30,30],
             (2,'Berlin'): [35,34,33,32,31],
             (2,'Paris'):  [39,38,39,40,41],
             (2,'London'): [45,44,43,42,41],
             (3,'Berlin'): [24,25,26,27,28],
             (3,'Paris'):  [24,24,25,26,27],
             (3,'London'): [29,29,29,30,31],
             ('2m','Berlin'): [1,2,3,4,5],
             ('2m','Paris'):  [2,3,4,5,6],
             ('2m','London'): [3,4,5,6,7]}
test_data = pd.DataFrame(test_dict, index=[1990,1991,1992,1993,1994]).transpose()

現在我想將變量 1 和 2 的所有值設置為 NaN,其中變量 1 到 3 的總和小於 98 或大於 102,即 1994 年柏林、1991 年巴黎以及 1990 年和 1991 年倫敦(見下文)。

我已經分配了一個新的 DataFrame

df_sum = test_data.loc[[1,2,3]].sum(level=1)
df_sum
        1990  1991  1992  1993  1994
Berlin    99   100   101   102   103
Paris     99    97    98    99   100
London   104   103   102   102   102

並設置

mask = (df_sum < 98) | (df_sum > 102)
mask
         1990   1991   1992   1993   1994
Berlin  False  False  False  False   True
Paris   False   True  False  False  False
London   True   True  False  False  False

df_summask顯然是非多索引數據幀,並且具有與 test_data.loc[1] 相同的維度,......現在我想做類似的事情

for var in [1,2]: test_data.loc[var][mask] = np.nan

我明白為什么這不起作用並產生 SettingWithCopy 警告。 但是,到目前為止,我還沒有找到一種(優雅的)方法來做到這一點。 我找到了這個線程 ( Pandas: Apply mask to multiindex dataframe ) 並認為這可能是正確的方向,但不同之處在於掩碼與原始多索引 dataframe 具有相同的尺寸。

任何幫助深表感謝。

編輯:我認為這不是一個優雅的解決方案,但它甚至不起作用,我真的不明白這種行為:

for var in range(1,4):
    tmp = test_data.loc[var].copy()
    tmp[test_mask] = np.nan
    test_data.loc[var] = tmp.copy()

這導致test_data.loc[1]...loc[2]...loc[3]都是 NaN,盡管tmp在應用test_mask后只有 4 個 NaN。

您收到警告是因為您使用的是視圖,而不是副本,但如果我理解正確,您需要的是:

# you had this bit, but groupby syntax is preferred
df_sum = test_data.loc[[1,2,3]].groupby(level=1).sum()

for city, years in ((df_sum < 98) | (df_sum > 102)).iterrows():
    # get the years for which condition is True
    for year in years[years].index:
        test_data.loc[(slice(1,2), city), year] = np.nan

這使用slice語法進行多索引選擇,您可以在此處閱讀更多相關信息。

暫無
暫無

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

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