繁体   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