【问题标题】:pandas multiindex - how to select second level when using columns?pandas multiindex - 使用列时如何选择第二级?
【发布时间】:2017-12-21 01:31:15
【问题描述】:

我有一个带有这个索引的数据框:

index = pd.MultiIndex.from_product([['stock1','stock2'...],['price','volume'...]])

df['stock1'] 是一个有用的结构,但我如何选择所有价格数据?我无法理解文档。

我尝试了以下方法,但没有成功:df[:,'price']df[:]['price']df.loc(axis=1)[:,'close']df['price]

如果这种索引样式由于某种原因被普遍认为是一个坏主意,那么什么是更好的选择?我应该将股票的多索引索引作为时间序列而不是列级别的标签吗?

非常感谢

编辑 - 我对列使用多索引,而不是索引(措辞让我更胜一筹)。文档中的示例侧重于多级索引而不是列结构。

【问题讨论】:

标签: python-3.x pandas


【解决方案1】:

我发现访问具有 MultiIndex 列的 DataFrame 中的二级列最直观的解决方案是使用 .locslice()

如果您的 DataFrame 带有

df
  stock1        stock2        stock3       
   price volume  price volume  price volume
0      1      2      3      4      5      6
1      2      3      4      5      6      7

使用df.loc[:, (slice(None), "price")]

将传递所有具有"price" 子列的列

  stock1  stock2  stock3       
   price   price   price 
0      1       3       5
1      2       4       6

df.loc[:, (slice(None), "price")] 中,loc : 的第一个参数传递所有行的结果,第二个参数(slice(None), "price") 是一个元组,负责选择所有第一级列(slice(None))和所有第二级列"price"的名字。

【讨论】:

    【解决方案2】:

    使用@JohnZwinck's data sample

    In [132]: df
    Out[132]:
                   0
    stock1 price   1
           volume  2
    stock2 price   3
           volume  4
    stock3 price   5
           volume  6
    

    选项 1:

    In [133]: df.loc[(slice(None), slice('price')), :]
    Out[133]:
                  0
    stock1 price  1
    stock2 price  3
    stock3 price  5
    

    选项 2:

    In [134]: df.loc[pd.IndexSlice[:, 'price'], :]
    Out[134]:
                  0
    stock1 price  1
    stock2 price  3
    stock3 price  5
    

    更新:

    但是如果对于第二个索引,我想选择除价格之外的所有内容 并且有多个值,因此枚举不是一种选择。是 有类似 slice(~'price')

    首先让我们命名索引级别:

    df = df.rename_axis(["lvl0", "lvl1"])
    

    现在我们可以使用df.query() 方法:

    In [18]: df.query("lvl1 != 'price'")
    Out[18]:
                   0
    lvl0   lvl1
    stock1 volume  2
    stock2 volume  4
    stock3 volume  6
    

    【讨论】:

    • 有效,但slice() 函数在做什么? python 网站对我没有帮助。所述 slice() 返回索引。我可以做类似 list(slice(...)) 的事情吗?显然不是。
    • @muuh,请查看this question and answers - 希望对您有所帮助...
    • 对于选项 1,这也适用:df.loc[(slice(None),'price'), :]。换句话说,要为该索引级别选择特定值,只需使用该值即可。
    • 很好的答案。但是,如果对于第二个索引,我想选择除 price 之外的所有内容,并且有多个值,因此枚举不是一个选项。有没有类似slice(~'price')
    • df.loc[pd.IndexSlice[:, 'price'], :] 中最后一个 : 是什么意思?另外,显然你可以做df.loc[:, 'price', :]...
    【解决方案3】:

    同样使用 John 的数据样本:

    使用xs() 是分割MultiIndex 的另一种方法:

    df
                   0
    stock1 price   1
           volume  2
    stock2 price   3
           volume  4
    stock3 price   5
           volume  6
    
    df.xs('price', level=1, drop_level=False)
                  0
    stock1 price  1
    stock2 price  3
    stock3 price  5
    

    或者,如果您使用MultiIndex 代替列:

    df
      stock1        stock2        stock3       
       price volume  price volume  price volume
    0      1      2      3      4      5      6
    
    df.xs('price', axis=1, level=1, drop_level=False)
      stock1 stock2 stock3
       price  price  price
    0      1      3      5
    

    【讨论】:

    • 非常感谢。由于我是 Multiindexing 的新手,我的问题写得不好。我对列使用多索引,而不是索引。 df.xs('price',axis=1,level=1) 完美地完成了这项工作
    • @AndyMoore 太棒了,很高兴为您提供帮助。
    • 这里只是说 .xs 在 pandas 1.1.3 中仍在使用:pandas.pydata.org/pandas-docs/stable/user_guide/advanced.html
    【解决方案4】:

    我还注意到您错过了这个选项:

    df.loc[:,"price"]
    

    就时间数据的最佳实践而言,将其保存在与行相对应的列中,最好作为 Python 中的 datetime 对象(pandas 已经内置了对它的功能支持)。您可以使用掩码语法仅获取与您的兴趣相关的时间。

    这就是您访问数据框单列的方式。但是对于多个列,我们可以传递一个列表,或者一个冒号来获取全部:

    df.loc[:,["price","volume"]] 
    #or
    df.loc[:,:]
    

    一种有用的查询(快速)方法是使用掩码来指定哪些行/列满足您想要的条件:

    Mask=df.loc[:,"price"]>50.0
    df.loc[Mask, "stock"] #should return the stock prices greater than 50bucks. 
    

    希望这会有所帮助,如果我完全误解了您的问题,请随时跟进此答案,我很乐意提供进一步的帮助。

    【讨论】:

    • 你在使用数据框吗?
    • 是的,在这里查看我的答案,了解我正在使用的精确 DataFrame。
    【解决方案5】:

    df.unstack() 将“撕掉”MultiIndex 的最后一层,并使您的 DataFrame 更加传统,每种类型的数据只有一列。例如:

    index = pd.MultiIndex.from_product([['stock1','stock2','stock3'],['price','volume']])
    df = pd.DataFrame([1,2,3,4,5,6], index)
    print(df.unstack())
    

    给你:

               0       
           price volume
    stock1     1      2
    stock2     3      4
    stock3     5      6
    

    【讨论】:

      猜你喜欢
      • 2020-06-05
      • 2021-06-18
      • 1970-01-01
      • 2017-07-03
      • 2019-09-04
      • 1970-01-01
      • 2013-08-30
      相关资源
      最近更新 更多