[英]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_sum
和mask
顯然是非多索引數據幀,並且具有與 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.