【问题标题】:Modifying a subset of a pandas MultiIndex修改 pandas MultiIndex 的子集
【发布时间】:2020-05-19 21:02:57
【问题描述】:

我有一个带有 MultiIndex 的 pandas DataFrame,我正在寻找一种快速的方法来修改我的一个 MultiIndex 级别的子集以用于某些级别。这是一个示例,我需要更改 2 个索引 (0, 10) 和 (9, 25) 并更改它们的“结束”级别。

import pandas as pd

# Make up some data
data = pd.DataFrame({
    'start': [0, 12, 9, 24],
    'end': [10, 20, 25, 32],
    'col1': ['a', 'b', 'a', 'd'],
    'col2': [1, 1, 2, 2]
}).set_index(['start', 'end'])

# Idx to change for the "end" level
idx_to_change = {(0, 10), (9, 25)}

### A cumbersome way to do it ###
data.reset_index(inplace=True)
subset = [True if (s, t) in idx_to_change else False for (s, t, _, _) in data.values]
data.loc[subset, 'end'] += 10

# Update the data
data.set_index(['start', 'end'], inplace=True)

如您所见,更改某些索引需要一点代码(而且可能特别慢)。你知道更好的方法吗?

感谢您的帮助

【问题讨论】:

    标签: python pandas multi-index


    【解决方案1】:

    一种方法是通过pd.MultiIndex重新分配索引:

    idx_to_change = {(0, 10), (9, 25)}
    
    data.index = pd.MultiIndex.from_tuples([i if i not in idx_to_change else (i[0],i[1]+10) for i in data.index], names=("start","end"))
    print (data)
    
              col1  col2
    start end           
    0     20     a     1
    12    20     b     1
    9     35     a     2
    24    32     d     2
    

    【讨论】:

    • 谢谢,这是最快的。我有点希望有一种方法可以在不遍历所有索引的情况下更改它,但我想没有办法解决它
    【解决方案2】:

    可以将 MultiIndex 转换为数据框,对其进行修改,然后将其重新分配为索引。

    data = pd.DataFrame({
        'start': [0, 12, 9, 24],
        'end': [10, 20, 25, 32],
        'col1': ['a', 'b', 'a', 'd'],
        'col2': [1, 1, 2, 2]
    }).set_index(['start', 'end'])
    
    # extract & modify the index
    idx = data.index.to_frame()
    idx.loc[[(0,10), (9,25)], 'end'] += 10
    
    # assign it back
    
    # in more recent versions of pandas (0.24+) the MultiIndex can be created 
    # directly from the data frame
    data.index = pd.MultiIndex.from_frame(idx[['start', 'end']])
    
    # with earlier versions the trick is to convert the dataframe `idx` to 
    # desired MultiIndex
    data.index = idx.reset_index(drop=True).set_index(['start','end']).index
    
    
    data
    # outputs
              col1  col2
    start end
    0     20     a     1
    12    20     b     1
    9     35     a     2
    24    32     d     2
    

    【讨论】:

    • 谢谢,很高兴知道(我不知道如何将 multiIndex 转换为数据框)。我尝试过这种方法,但它似乎比亨利的慢
    【解决方案3】:

    一种方法是,您可以将索引作为列表取出并在更新后重新分配;

    idx_to_change = {(0, 10), (9, 25)}
    as_list = data.index.tolist()
    for idx_change in idx_to_change:
        idx = as_list.index(idx_change)
        as_list[idx] = (as_list[idx][0], list(as_list[idx])[1] + 10) #tuple is immutable so need to be converted to list
    data.index = as_list
    

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 2015-05-22
      • 2013-07-07
      • 2016-12-31
      • 2012-08-31
      • 2020-02-15
      • 2017-07-22
      • 2019-04-11
      • 1970-01-01
      相关资源
      最近更新 更多