选择/筛选adataframe whose index is a MultiIndex的行的最常见pandas方法是什么?
简单性假设:
mux = pd.MultiIndex.from_arrays([ list('aaaabbbbbccddddd'), list('tuvwtuvwtuvwtuvw') ], names=['one', 'two']) df = pd.DataFrame({'col': np.arange(len(mux))}, mux) col one two a t 0 u 1 v 2 w 3 b t 4 u 5 v 6 w 7 t 8 c u 9 v 10 d w 11 t 12 u 13 v 14 w 15
如何在级别“一”中选择具有“a”的行?
col
one two
a t 0
u 1
v 2
w 3
另外,我如何才能在输出中降低级别“1”?
col
two
t 0
u 1
v 2
w 3
问题1b
如何对级别“2”上值为“t”的所有行进行切片?
col
one two
a t 0
b t 4
t 8
d t 12
如何选择“一级”中“b”和“d”项对应的行?
col
one two
b t 4
u 5
v 6
w 7
t 8
d w 11
t 12
u 13
v 14
w 15
问题2b
我如何得到与“t”和“w”对应的所有值?
col
one two
a t 0
w 3
b t 4
w 7
t 8
d w 11
t 12
w 15
(x, y)
如何从df
检索横截面,即具有索引特定值的单行?具体来说,如何检索('c', 'u')
的横截面,由
col
one two
c u 9
[(a, b), (c, d), ...]
如何选择对应于('c', 'u')
和('a', 'w')
的两行?
col
one two
c u 9
a w 3
如何检索与级别“1”中的“a”或级别“2”中的“t”对应的所有行?
col
one two
a t 0
u 1
v 2
w 3
b t 4
t 8
d t 12
如何分割特定的横截面?对于“a”和“b”,我想选择所有子级别为“u”和“v”的行,对于“d”,我想选择子级别为“w”的行。
col
one two
a u 1
v 2
b u 5
v 6
d w 11
w 15
Question 7 will use a unique setup consisting of a numeric level:
np.random.seed(0) mux2 = pd.MultiIndex.from_arrays([ list('aaaabbbbbccddddd'), np.random.choice(10, size=16) ], names=['one', 'two']) df2 = pd.DataFrame({'col': np.arange(len(mux2))}, mux2) col one two a 5 0 0 1 3 2 3 3 b 7 4 9 5 3 6 5 7 2 8 c 4 9 7 10 d 6 11 8 12 8 13 1 14 6 15
如何获取级别“2”中的值大于5的所有行?
col
one two
b 7 4
9 5
c 7 10
d 6 11
8 12
8 13
6 15
注意:这篇文章将而不是介绍如何创建多索引,如何对它们执行赋值操作,或任何与性能相关的讨论(这些是以后单独讨论的主题)。
MultiIndex / Advanced Indexing
以下是一些常见的习语(以下简称“四个习语”)的介绍,我们将经常重访
^{} -按标签选择的通用解决方案(对于涉及切片的更复杂应用程序,+^{} )
^{} -从序列/数据帧中提取特定的横截面。
^{} -动态指定切片和/或筛选操作(即,作为动态计算的表达式)。更适用于某些场景。有关查询多索引的信息,请参见this section of the docs。
使用^{} 生成的掩码的布尔索引(通常与^{} 结合使用,特别是在使用多个值进行筛选时)。这在某些情况下也是非常有用的。
从这四个习语的角度来看各种切片和过滤问题,将有助于更好地理解什么可以应用于给定的情况。很重要的一点是,并非所有的习语在任何情况下都能起到同样的作用(如果有的话)。如果一个习语没有被列为解决下面问题的潜在方法,那就意味着习语不能有效地应用于这个问题。
您可以使用
loc
,作为适用于大多数情况的通用解决方案:在这一点上,如果你
这意味着你用的是旧版的熊猫。考虑升级!否则,请使用
df.loc[('a', slice(None)), :]
。或者,您可以在这里使用
xs
,因为我们提取的是单个横截面。注意levels
和axis
参数(这里可以假设合理的默认值)。这里,需要
drop_level=False
参数来防止xs
在结果中删除级别“one”(我们切片的级别)。这里还有一个选项是使用
query
:如果索引没有名称,则需要将查询字符串更改为
"ilevel_0 == 'a'"
。最后,使用
get_level_values
:这可以使用
或者
注意,我们可以省略
drop_level
参数(默认情况下假定为True
)。直觉上,你会想要一些涉及^{} 的东西:
它只是工作!™ 但它很笨重。我们可以在这里使用
pd.IndexSlice
API来简化更自然的切片语法。这要干净得多。
对于
xs
,它是对于
query
,它是最后,使用
get_level_values
,您可以都有同样的效果。
使用loc,通过指定一个列表以类似的方式完成。
要解决上述选择“b”和“d”的问题,还可以使用
query
:并且,使用
get_level_values
+Index.isin
:有了
loc
,这只可能与pd.IndexSlice
结合使用。在
pd.IndexSlice[:, ['t', 'w']]
中,第一个冒号:
表示在第一个级别上进行切片。随着所查询级别的深度增加,您将需要指定更多的切片,每个切片级别一个切片。但是,除了要切片的级别之外,您不需要指定更多级别。使用
query
,这是使用
get_level_values
和Index.isin
(与上面类似):通过指定一个键元组来使用
loc
:或者
对于
xs
,这再次简单地将一个元组作为第一个参数传递,所有其他参数都设置为相应的默认值:随着
query
,事情变得有点笨拙:现在你可以看到这是g总的来说比较难概括。但对于这个特殊的问题还是可以的。
对于跨越多个级别的访问,
get_level_values
仍然可以使用,但不建议使用:对于
loc
,这仍然是简单的:使用
query
,您将需要通过遍历横截面和级别动态生成查询字符串:100%不推荐!但这是可能的。
这实际上很难在确保正确性的同时保持代码的清晰性。
df.loc[pd.IndexSlice['a', 't']]
不正确,它被解释为df.loc[pd.IndexSlice[('a', 't')]]
(即选择横截面)。您可以考虑使用pd.concat
来分别处理每个标签的解决方案:但您会注意到其中一行是重复的。这是因为该行同时满足两个切片条件,因此出现了两次。你需要做的是
但是,如果数据帧固有地包含重复的索引(您需要的),那么这将不会保留它们。慎用。
对于
query
,这非常简单:对于
get_level_values
,这仍然很简单,但没有那么优雅:这是我为帮助理解四个习语的适用性而添加的一个特殊情况这是一个没有任何习语都能有效工作的情况,因为切片是非常特定的,并且不遵循任何实际模式。
通常,像这样的切片问题需要显式地将键列表传递给
loc
。一种方法是:如果您想保存一些类型,您将认识到有一个模式可以对“a”、“b”及其子级别进行切片,因此我们可以将切片任务分成两部分并
concat
结果:“a”和“b”的切片规范稍微干净一些,因为索引的相同子级别对于每个级别都是相同的。
这可以使用
query
以及
get_level_values
。实际上,这里的大多数解决方案也适用于列,只需稍作更改。考虑:
以下是您需要对四个习惯用法进行的更改,以使它们能够处理列。
要使用
loc
切片,请使用或者
要酌情使用
xs
,只需传递一个参数axis=1
。可以使用
df.columns.get_level_values
直接访问列级值。然后你需要做一些其中
{condition}
表示使用columns.get_level_values
生成的某些条件。要使用
query
,您唯一的选择是转置、查询索引并再次转置:不推荐,使用其他3个选项之一。
最近我遇到了一个用例,我有一个3+级别的多索引数据框架,在这个框架中,我无法使上面的任何解决方案产生我正在寻找的结果。上面的解决方案很有可能对我的用例起作用,我尝试了几个,但是在我有时间的时候,我无法让它们起作用。
我不是专家,但我偶然发现了一个没有在上面的综合答案中列出的解决方案。我不能保证这些解决方案在任何方面都是最优的。
对于上面的问题6,这是获得稍微不同结果的不同方法。(以及可能的其他问题)
特别是我要找的:
作为齿轮上的活动扳手(尽管完全固定):
在下面的玩具数据框上:
当然,使用以下作品:
但我想要一个不同的结果,所以我得到这个结果的方法是:
如果我想要一个级别的两个+值和另一个级别的一个(或2+)值:
上面的方法可能有点笨拙,但我发现它满足了我的需要,作为奖励,我更容易理解和阅读。
相关问题 更多 >
编程相关推荐