Python 选择多索引数据框中的行
选择/筛选行的最常用方法是什么?Python 选择多索引数据框中的行,python,pandas,dataframe,slice,multi-index,Python,Pandas,Dataframe,Slice,Multi Index,选择/筛选行的最常用方法是什么? 基于单个值/标签的切片 基于一个或多个级别的多个标签进行切片 布尔条件和表达式的过滤 哪些方法适用于什么情况 为简单起见,假设: 输入数据帧没有重复的索引键 下面的输入数据帧只有两个级别。(此处显示的大多数解决方案可推广到N个级别) 输入示例: 问题1:选择单个项目 如何选择级别“1”中具有“a”的行 此外,我如何才能在输出中降低级别“1” col two t 0 u 1 v 2 w 3
- 基于单个值/标签的切片
- 基于一个或多个级别的多个标签进行切片
- 布尔条件和表达式的过滤
- 哪些方法适用于什么情况
输入示例: 问题1:选择单个项目 如何选择级别“1”中具有“a”的行 此外,我如何才能在输出中降低级别“1”
col
two
t 0
u 1
v 2
w 3
col
two
t 0
u 1
v 2
w 3
问题1b如何在级别“2”上对值为“t”的所有行进行切片 问题2:在一个级别中选择多个值 如何选择级别“一”中项目“b”和“d”对应的行 问题2b
如何获得级别“2”中与“t”和“w”对应的所有值 问题3:切片单个横截面
(x,y)
如何从df
检索横截面,即具有特定索引值的单行?具体来说,如何检索('c','u')
的横截面,由
col
one two
c u 9
col
one two
c u 9
问题4:切片多个横截面[(a,b),(c,d),…]
如何选择与('c','u')
和('a','w')
相对应的两行
问题5:每级切片一个项目
如何检索与级别“1”中的“a”或级别“2”中的“t”对应的所有行
问题6:任意切片
如何切片特定的横截面?对于“a”和“b”,我想选择所有子级别为“u”和“v”的行,对于“d”,我想选择子级别为“w”的行
问题7将使用由数字级别组成的唯一设置:
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
问题7:在多指标的各个层次上通过数值不等式进行过滤
如何获取级别“2”中的值大于5的所有行
col
one two
b 7 4
9 5
c 7 10
d 6 11
8 12
8 13
6 15
col
one two
b 7 4
9 5
c 7 10
d 6 11
8 12
8 13
6 15
注意:这篇文章将不讨论如何创建多索引,如何对它们执行赋值操作,或者任何与性能相关的讨论(这些是另一次单独讨论的主题) 注意
该员额的结构将如下:
问题1 如何选择级别“1”中具有“a”的行 您可以使用
loc
,作为适用于大多数情况的通用解决方案:
df.loc[['a']]
在这一点上,如果你
TypeError: Expected tuple, got str
这意味着你在使用一个较老版本的大熊猫。考虑升级,否则,使用<代码> df.LOC[ [(a,'切片(无)]:] /<代码>
或者,您可以在此处使用xs
,因为我们提取的是单个横截面。请注意级别
和轴
参数(此处可以假设合理的默认值)
在这里,需要使用drop_level=False
参数来防止xs
在结果中删除级别“1”(我们切片的级别)
这里的另一个选项是使用query
:
df.query("one == 'a'")
items = ['b', 'd']
df.query("one in @items")
# df.query("one == @items", parser='pandas')
# df.query("one in ['b', 'd']")
# df.query("one == ['b', 'd']", parser='pandas')
如果索引没有名称,则需要将查询字符串更改为“ilevel_0=='a'”
最后,使用获取级别值:
df[df.index.get_level_values('one') == 'a']
# If your levels are unnamed, or if you need to select by position (not label),
# df[df.index.get_level_values(0) == 'a']
此外,我如何才能在输出中降低级别“1”
col
two
t 0
u 1
v 2
w 3
col
two
t 0
u 1
v 2
w 3
这可以通过以下两种方法轻松实现:
df.loc['a'] # Notice the single string argument instead the list.
或者
请注意,我们可以省略drop\u level
参数(默认情况下,它假定为True
)
注意
您可能会注意到,经过筛选的数据帧可能仍然具有所有级别,即使在打印数据帧时没有显示这些级别。例如
v = df.loc[['a']]
print(v)
col
one two
a t 0
u 1
v 2
w 3
print(v.index)
MultiIndex(levels=[['a', 'b', 'c', 'd'], ['t', 'u', 'v', 'w']],
labels=[[0, 0, 0, 0], [0, 1, 2, 3]],
names=['one', 'two'])
您可以使用以下方法消除这些级别:
问题1b
如何在级别上对值为“t”的所有行进行切片
df.query("one == 'a'")
df[df.index.get_level_values('one') == 'a']
# If your levels are unnamed, or if you need to select by position (not label),
# df[df.index.get_level_values(0) == 'a']
col
two
t 0
u 1
v 2
w 3
df.loc['a'] # Notice the single string argument instead the list.
df.xs('a', level=0, axis=0, drop_level=True)
# df.xs('a')
v = df.loc[['a']]
print(v)
col
one two
a t 0
u 1
v 2
w 3
print(v.index)
MultiIndex(levels=[['a', 'b', 'c', 'd'], ['t', 'u', 'v', 'w']],
labels=[[0, 0, 0, 0], [0, 1, 2, 3]],
names=['one', 'two'])
v.index = v.index.remove_unused_levels()
print(v.index)
MultiIndex(levels=[['a'], ['t', 'u', 'v', 'w']],
labels=[[0, 0, 0, 0], [0, 1, 2, 3]],
names=['one', 'two'])
col
one two
a t 0
b t 4
t 8
d t 12
df.loc[(slice(None), 't'), :]
idx = pd.IndexSlice
df.loc[idx[:, 't'], :]
df.loc(axis=0)[pd.IndexSlice[:, 't']]
df.xs('t', axis=0, level=1, drop_level=False)
df.query("two == 't'")
# Or, if the first level has no name,
# df.query("ilevel_1 == 't'")
df[df.index.get_level_values('two') == 't']
# Or, to perform selection by position/integer,
# df[df.index.get_level_values(1) == 't']
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
df.loc[['b', 'd']]
items = ['b', 'd']
df.query("one in @items")
# df.query("one == @items", parser='pandas')
# df.query("one in ['b', 'd']")
# df.query("one == ['b', 'd']", parser='pandas')
df[df.index.get_level_values("one").isin(['b', 'd'])]
col
one two
a t 0
w 3
b t 4
w 7
t 8
d w 11
t 12
w 15
df.loc[pd.IndexSlice[:, ['t', 'w']], :]
items = ['t', 'w']
df.query("two in @items")
# df.query("two == @items", parser='pandas')
# df.query("two in ['t', 'w']")
# df.query("two == ['t', 'w']", parser='pandas')
df[df.index.get_level_values('two').isin(['t', 'w'])]
col
one two
c u 9
df.loc[('c', 'u'), :]
df.loc[pd.IndexSlice[('c', 'u')]]
PerformanceWarning: indexing past lexsort depth may impact performance.
df_sort = df.sort_index()
df_sort.loc[('c', 'u')]
df.xs(('c', 'u'))
df.query("one == 'c' and two == 'u'")
m1 = (df.index.get_level_values('one') == 'c')
m2 = (df.index.get_level_values('two') == 'u')
df[m1 & m2]
col
one two
c u 9
a w 3
df.loc[[('c', 'u'), ('a', 'w')]]
# df.loc[pd.IndexSlice[[('c', 'u'), ('a', 'w')]]]
cses = [('c', 'u'), ('a', 'w')]
levels = ['one', 'two']
# This is a useful check to make in advance.
assert all(len(levels) == len(cs) for cs in cses)
query = '(' + ') or ('.join([
' and '.join([f"({l} == {repr(c)})" for l, c in zip(levels, cs)])
for cs in cses
]) + ')'
print(query)
# ((one == 'c') and (two == 'u')) or ((one == 'a') and (two == 'w'))
df.query(query)
df[df.index.droplevel(unused_level).isin([('c', 'u'), ('a', 'w')])]
col
one two
a t 0
u 1
v 2
w 3
b t 4
t 8
d t 12
pd.concat([
df.loc[['a'],:], df.loc[pd.IndexSlice[:, 't'],:]
])
col
one two
a t 0
u 1
v 2
w 3
t 0 # Does this look right to you? No, it isn't!
b t 4
t 8
d t 12
v = pd.concat([
df.loc[['a'],:], df.loc[pd.IndexSlice[:, 't'],:]
])
v[~v.index.duplicated()]
df.query("one == 'a' or two == 't'")
m1 = (df.index.get_level_values('one') == 'a')
m2 = (df.index.get_level_values('two') == 't')
df[m1 | m2]
col
one two
a u 1
v 2
b u 5
v 6
d w 11
w 15
keys = [('a', 'u'), ('a', 'v'), ('b', 'u'), ('b', 'v'), ('d', 'w')]
df.loc[keys, :]
pd.concat([
df.loc[(('a', 'b'), ('u', 'v')), :],
df.loc[('d', 'w'), :]
], axis=0)
col
one two
b 7 4
9 5
c 7 10
d 6 11
8 12
8 13
6 15
df2.query("two > 5")
df2[df2.index.get_level_values('two') > 5]
np.random.seed(0)
mux3 = pd.MultiIndex.from_product([
list('ABCD'), list('efgh')
], names=['one','two'])
df3 = pd.DataFrame(np.random.choice(10, (3, len(mux))), columns=mux3)
print(df3)
one A B C D
two e f g h e f g h e f g h e f g h
0 5 0 3 3 7 9 3 5 2 4 7 6 8 8 1 6
1 7 7 8 1 5 9 8 9 4 3 0 3 5 0 2 3
2 8 1 3 3 3 7 0 1 9 9 0 4 7 3 2 7
df3.loc[:, ....] # Notice how we slice across the index with `:`.
df3.loc[:, pd.IndexSlice[...]]
df.loc[:, {condition}]
df3.T.query(...).T
index = pd.MultiIndex.from_product([['a','b'],
['stock1','stock2','stock3'],
['price','volume','velocity']])
df = pd.DataFrame([1,2,3,4,5,6,7,8,9,
10,11,12,13,14,15,16,17,18],
index)
0
a stock1 price 1
volume 2
velocity 3
stock2 price 4
volume 5
velocity 6
stock3 price 7
volume 8
velocity 9
b stock1 price 10
volume 11
velocity 12
stock2 price 13
volume 14
velocity 15
stock3 price 16
volume 17
velocity 18
df.xs(('stock1', 'velocity'), level=(1,2))
0
a 3
b 12
df.iloc[df.index.isin(['stock1'], level=1) &
df.index.isin(['velocity'], level=2)]
0
a stock1 velocity 3
b stock1 velocity 12
df.iloc[df.index.isin(['stock1','stock3'], level=1) &
df.index.isin(['velocity'], level=2)]
0
a stock1 velocity 3
stock3 velocity 9
b stock1 velocity 12
stock3 velocity 18
df.sql(<SQL select statement>)